Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Быстрый алгоритм подсчета CRC32

Delphi , Синтаксис , Шифрование



Автор: Александр Шарахов
WEB-сайт: http://delphibase.endimus.com

{ **** UBPFD *********** by delphibase.endimus.com ****
>> 
Использован BASM.

Зависимости: нет
Автор:       Александр Шарахов, alsha@mailru.com, Москва
Copyright:   Александр Шарахов
Дата:        18 января 2003 г.
***************************************************** }

unit CRCunit;

interface
function GetNewCRC(OldCRC: cardinal; StPtr: pointer; StLen: integer): cardinal;
procedure UpdateCRC(StPtr: pointer; StLen: integer; var CRC: cardinal);
function GetZipCRC(StPtr: pointer; StLen: integer): cardinal;
function GetFileCRC(const FileName: string): cardinal;

implementation
var
  CRCtable: array[0..255] of cardinal;

function GetNewCRC(OldCRC: cardinal; StPtr: pointer; StLen: integer): cardinal;
asm
  test edx,edx;
  jz @ret;
  neg ecx;
  jz @ret;
  sub edx,ecx; // Address after last element

  push ebx;
  mov ebx,0; // Set ebx=0 & align @next
@next:
  mov bl,al;
  xor bl,byte [edx+ecx];
  shr eax,8;
  xor eax,cardinal [CRCtable+ebx*4];
  inc ecx;
  jnz @next;
  pop ebx;

@ret:
end;

procedure UpdateCRC(StPtr: pointer; StLen: integer; var CRC: cardinal);
begin
  CRC := GetNewCRC(CRC, StPtr, StLen);
end;

function GetZipCRC(StPtr: pointer; StLen: integer): cardinal;
begin
  Result := not GetNewCRC($FFFFFFFF, StPtr, StLen);
end;

function GetFileCRC(const FileName: string): cardinal;
const
  BufSize = 64 * 1024;
var
  Fi: file;
  pBuf: PChar;
  Count: integer;
begin
  Assign(Fi, FileName);
  Reset(Fi, 1);
  GetMem(pBuf, BufSize);
  Result := $FFFFFFFF;
  repeat
    BlockRead(Fi, pBuf^, BufSize, Count);
    if Count = 0 then
      break;
    Result := GetNewCRC(Result, pBuf, Count);
  until false;
  Result := not Result;
  FreeMem(pBuf);
  CloseFile(Fi);
end;

procedure CRCInit;
var
  c: cardinal;
  i, j: integer;
begin
  for i := 0 to 255 do
  begin
    c := i;
    for j := 1 to 8 do
      if odd(c) then
        c := (c shr 1) xor $EDB88320
      else
        c := (c shr 1);
    CRCtable[i] := c;
  end;
end;

initialization
  CRCinit;
end.

Пример использования:

uses
  CRCunit;

procedure TForm1.Button1Click(Sender: TObject);
const
  FileName = 'CRCunit.pas';
begin
  ShowMessage('CRC32 файла=' + IntToHex(GetFileCRC(FileName), 8));
  ShowMessage('CRC32 имени=' + IntToHex(GetZipCRC(PChar(FileName),
    Length(FileName)), 8));
end;

Перевод контента на русский язык:

Единица Delphi, которая обеспечивает быстрый алгоритм расчета контрольной суммы CRC32 (Cyclic Redundancy Check). Единица включает в себя четыре функции:

  1. GetNewCRC: рассчитывает контрольную сумму CRC32 для блока данных.
  2. UpdateCRC: обновляет контрольную сумму CRC32, добавляя новый блок данных.
  3. GetZipCRC: рассчитывает контрольную сумму CRC32 для строки (например, имени файла) с использованием алгоритма ZIP.
  4. GetFileCRC: рассчитывает контрольную сумму CRC32 для файла.

Единица использует ассемблерный язык для оптимизации расчета CRC, который обычно выполняется в программном обеспечении. Функция GetNewCRC использует таблицу lookup (CRCtable) для ускорения расчета.

Вот некоторые наблюдения и предложения:

  • Код хорошо структурирован и легко понятен.
  • Использование ассемблерного языка для расчета CRC эффективно улучшает производительность.
  • Функция GetZipCRC не необходима, поскольку она просто вызывает функцию GetNewCRC с конкретным начальными значениями ($FFFFFFFF) и затем инвертирует результат. Это можно заменить простым оберткой вокруг функции GetNewCRC.
  • Функция GetFileCRC читает файл по блокам в 64 КБ (используя BlockRead) и обновляет контрольную сумму CRC для каждого блока. Это эффективно, но может быть стоить рассмотреть использование более крупного буфера или даже потокового чтения содержимого файла напрямую в расчет CRC.
  • В единице нет механизмов обработки ошибок. Например, что происходит, если файл, указанный в GetFileCRC, не может быть открыт?
  • Код не включает в себя документацию или комментарии за пределами начального заголовка.

Альтернативное решение для расчета контрольной суммы CRC32 файла:

function GetFileCRC(const FileName: string): cardinal;
var
  Fi: file;
  Buf: array[0..65535] of byte; // Более крупный буфер для лучшей производительности
begin
  Assign(Fi, FileName);
  Reset(Fi, 1);
  try
    Result := $FFFFFFFF;
    BlockRead(Fi, Buf, Length(Buf));
    while not Eof(Fi) do
    begin
      Result := GetNewCRC(Result, @Buf[0], Length(Buf));
      BlockRead(Fi, Buf, Length(Buf));
    end;
  finally
    CloseFile(Fi);
  end;
end;

В этом альтернативном решении я использовал более крупный буфер (64 КБ) для уменьшения количества вызовов GetNewCRC. Я также добавил обработку ошибок с помощью блоков try-finally, чтобы обеспечить закрытие файла, даже если возникнет исключение.

В статье описан быстрый алгоритм подсчета CRC32, реализованный на языке Delphi с использованием ассемблерных инструкций.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Шифрование ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-01-29 05:47:30/0.0035278797149658/0