Einzelnen Beitrag anzeigen

PeterPanino

Registriert seit: 4. Sep 2004
1.451 Beiträge
 
Delphi 10.4 Sydney
 
#5

AW: Datei auf Indikatoren für Binärdatei testen?

  Alt 9. Mai 2015, 13:57
Ich habe die Funktion jetzt erweitert:

1. Testen auf Doppel-NullBytes anstatt auf einfache NullBytes

2. Testen auf mehr als n verbotene ControlBytes

Delphi-Quellcode:
function IsTextFile(const AFile: string; const ABytesCount: Integer = 1000): Boolean;
// testet, ob die ersten ABytesCount Bytes einer Datei Indikatoren für eine Binär-Datei enthalten:
// wenn nicht, muss es wohl eine Textdatei sein?
// Siehe auch: http://qc.embarcadero.com/wc/qcmain.aspx?d=84071
const
  MaxAllowedForbiddenControlCharsCount = 1;
var
  Reader: TStreamReader;
  Ch: AnsiChar;
  c: Integer;
  PreviousCharWasNullByte: Boolean;
  ForbiddenControlCharsCount: Integer;
begin
  Result := True;
  c := 0;
  PreviousCharWasNullByte := False;
  ForbiddenControlCharsCount := 0;

  Reader := TStreamReader.Create(TFileStream.Create(AFile, fmOpenRead), TEncoding.ANSI);
  try
    if Reader.EndOfStream then
    begin
      CodeSite.Send('Nothing to read');
      Result := False;
      EXIT;
    end;

    while Reader.Peek() >= 0 do
    begin
      Ch := AnsiChar(Reader.Read());

      if Ch = #0 then
      begin
        if PreviousCharWasNullByte then
        begin
          CodeSite.Send('Double Null Byte found');
          Result := False;
          EXIT;
        end;
        PreviousCharWasNullByte := True;
      end
      else
      begin
        PreviousCharWasNullByte := False;

        if Ch in [#1..#8, #14..#31] then
        begin
          Inc(ForbiddenControlCharsCount);
          CodeSite.Send('This forbidden control char', HexDisplayPrefix + IntToHex(Ord(Ch), 2));
        end;
        if ForbiddenControlCharsCount > MaxAllowedForbiddenControlCharsCount then
        begin
          CodeSite.Send('More than ' + IntToStr(MaxAllowedForbiddenControlCharsCount) + ' forbidden control chars found');
          Result := False;
          EXIT;
        end;
      end;

      // Todo: andere Indikatoren?

      Inc(c);
      if c > ABytesCount then EXIT;
    end;
  finally
    CodeSite.Send('Bytes read', c);
    Reader.Close();
    Reader.BaseStream.Free;
    Reader.Free();
  end;
end;

procedure TForm1.btnTestClick(Sender: TObject);
var
  d: Int64;
begin
  d := GetTickCount;
  CodeSite.Send('Is Text File?', IsTextFile(edt1.Text));
  CodeSite.Send('Duration', GetTickCount - d);
end;
  Mit Zitat antworten Zitat