Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi "binäre" Dateien (https://www.delphipraxis.net/45172-binaere-dateien.html)

bigg 1. Mai 2005 03:43


"binäre" Dateien
 
Liste der Anhänge anzeigen (Anzahl: 1)
:hi:

nun ja, da mir Mabuse einen sehr guten Tipp für die Integration einer
Hex-Ansicht für meinen Editor gegeben hat, habe ich mir nun einige kleine
Routinen geschrieben, die mir dies ermöglichen werden.

Diese Funktion überprüft, ob eine Datei von einem Texteditor gelesen
werden kann oder nicht. Es wäre schön, wenn ihr diesen Ablauf einmal
bei euch testen könntet und mir mögliche Fehlerquellen zukommen läßt.
Optimierungen sind selbstverständlich, willkommen. :stupid:

Delphi-Quellcode:
////////////////////////////////////////////////////////////////////////////////
// Methode 1: TFileStream
// Prüft, ob sich in einer Datei binäre Zeichen befinden
////////////////////////////////////////////////////////////////////////////////

function TForm1.IsBinaryFile(FileName: String): Integer;
const MAX_Buffer = 2048; // Puffer in Byte pro Block
      Forbidden: Set of Byte = [0..8, 11, 14..31]; // typische Binärzeichen
var  FileStream: TFileStream;
      Buffer: Array[1..MAX_Buffer] of Byte; // Datenpuffer
      FileSize: Int64;
      Blocks, Last, i, f, BufferSize, ActSize: Integer;
begin
  Result := 0;
  ActSize := 0;

  if FileExists(FileName) then
  begin // die Datei existiert, also lesen wir sie ein
     try
        FileStream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone);
     except
        Result := -2; // Datei wird von einem anderen Prozess verwendet
        Exit;
      end;

      try
        FileSize := FileStream.Size;          // Dateigröße in Byte
        Blocks  := (FileSize div MAX_Buffer); // Anzahl max. Blöcke
        Last    := (FileSize mod MAX_Buffer); // Größe des Rest-Puffer

        if Last <> 0 then
        inc(Blocks); // sofern, unser Restpuffer ungleich 0 Byte groß ist, wird unsere Blockvariable um 1 erhöht

        for i := 0 to Blocks -1 do // Blöcke einlesen
        begin
          if Result = 1 then
          Break; // spring aus der Schleife, wenn ein binäres Zeichen gefunden wurde

          FileStream.Position := ActSize; // Start-Position in Byte (wird von Block zu Block angepasst)

          inc(ActSize, MAX_Buffer);
          if ActSize <= FileSize then
          BufferSize := MAX_Buffer else
          BufferSize := Last;

          FileStream.ReadBuffer(Buffer[1], BufferSize);

          for f := 1 to BufferSize do
          begin // den eingelesenen Puffer durchsuchen
            if Result = 1 then
            Break; // spring aus der Schleife, wenn ein binäres Zeichen gefunden wurde

              if Buffer[f] < 32 then
              begin if Buffer[f] in Forbidden then
                begin
                  Result := 1; // ein binäres Zeichen wurde gefunden
                  Break;
                end;
              end;
          end;
        end;
      finally FileStream.Free;
      end;
  end else
  Result := -1; // Datei existiert nicht
end;

////////////////////////////////////////////////////////////////////////////////
// Methode 2: BlockRead
// Prüft, ob sich in einer Datei binäre Zeichen befinden
////////////////////////////////////////////////////////////////////////////////

function TForm1.IsBinaryFile2(FileName: String): Integer;
const MAX_Buffer = 2048; // Puffer in Byte pro Block
      Forbidden: Set of Byte = [0..8, 11, 14..31]; // typische Binärzeichen
var  AFile: File;
      Buffer: Array[1..MAX_Buffer] of Byte; // Datenpuffer
      FSize: Int64;
      Blocks, Last, i, f, BufferSize, ActSize: Integer;
begin
  Result := 0;
  ActSize := 0;

 if FileExists(FileName) then
 begin // die Datei existiert, also lesen wir sie ein
  AssignFile(AFile, FileName);

  {$i-}
  Reset(AFile, 1);
  {$i+}

  if IOResult = 0 then // Datei ist geöffnet...
  begin
    try
      FileMode := fmOpenRead or fmShareDenyNone;

      FSize := FileSize(AFile);       // Dateigröße in Byte
      Blocks := (FSize div MAX_Buffer); // Anzahl max. Blöcke
      Last  := (FSize mod MAX_Buffer); // Größe des Rest-Puffer

      if Last <> 0 then
      inc(Blocks); // sofern, unser Restpuffer ungleich 0 Byte groß ist, wird unsere Blockvariable um 1 erhöht

      for i := 0 to Blocks -1 do // Blöcke einlesen
      begin
        if Result = 1 then
        Break; // spring aus der Schleife, wenn ein binäres Zeichen gefunden wurde

        Seek(AFile, ActSize); // Start-Position in Byte (wird von Block zu Block angepasst)

        inc(ActSize, MAX_Buffer);
        if ActSize <= FSize then
        BufferSize := MAX_Buffer else
        BufferSize := Last;

        BlockRead(AFile, Buffer[1], BufferSize);

        for f := 1 to BufferSize do
        begin // den eingelesenen Puffer durchsuchen
          if Result = 1 then
          Break; // spring aus der Schleife, wenn ein binäres Zeichen gefunden wurde

            if Buffer[f] < 32 then
            begin if Buffer[f] in Forbidden then
              begin
                Result := 1; // ein binäres Zeichen wurde gefunden
                Break;
              end;
            end;
        end;
      end;
    finally CloseFile(AFile);
    end;
  end else Result := -2; // Datei wird von einem fremden Prozess verwendet
 end else Result := -1; // Datei existiert nicht
end;

Nicodius 1. Mai 2005 07:34

Re: "binäre" Dateien
 
würde ich hierher geben "Neuen Beitrag zur Code-Library hinzufügen" ist ja wichtig

Phistev 1. Mai 2005 13:38

Re: "binäre" Dateien
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich habe mich mal drangesetzt, den Code zu optimieren, und habe eine Verbesserung um den Faktor 4-5 geschafft :mrgreen: (etwa 6,4 MB/sec zu etwa 28,7 MB/sec). Code ist im Anhang, die Testdatei (80 MB, nicht binär, nicht zufällig erstellt) gibt es auf Anfrage.

/edit: Enthält noch nicht Result:=-2

bigg 1. Mai 2005 13:40

Re: "binäre" Dateien
 
Zitat:

Zitat von Nicodius
würde ich hierher geben "Neuen Beitrag zur Code-Library hinzufügen" ist ja wichtig

Ich habe noch eine Kleinigkeit abgeändert.
PS: Wenn die Mods nichts dagegen haben, kann der Thread verschoben werden.^^

bigg 1. Mai 2005 13:48

Re: "binäre" Dateien
 
Zitat:

Zitat von Phistev
Ich habe mich mal drangesetzt, den Code zu optimieren, und habe eine Verbesserung um den Faktor 4-5 geschafft :mrgreen: (etwa 6,4 MB/sec zu etwa 28,7 MB/sec). Code ist im Anhang, die Testdatei (80 MB, nicht binär, nicht zufällig erstellt) gibt es auf Anfrage.

/edit: Enthält noch nicht Result:=-2

Das kann dann aber nur am Set liegen :???:
Danke für diesen Hinweis :zwinker:

bigg 1. Mai 2005 15:40

Re: "binäre" Dateien
 
So, die neue Version ist nun deutlich schneller geworden,
sofern man große Textdateien damit überprüfen möchte.

Im Schnitt 40% schneller als Phistev modifizierte Version.

Phistev 1. Mai 2005 16:50

Re: "binäre" Dateien
 
Liste der Anhänge anzeigen (Anzahl: 1)
Wenn man das Set durch eine Abfrage wie
Delphi-Quellcode:
if (Buffer[f] < 32) and (Buffer[f] <> 9) and (Buffer[f] <> 10) and (Buffer[f] <> 13) then
ersetzt, kann man nochmal etwa 65-70 % rausholen :mrgreen:; inzwischen sind wir bei Geschwindigkeiten von ca. 150-160 MB/sec :o . Ich teste mal, wie schnell eine file of byte wäre, nur aus akademischem Interesse...

/edit: Das mit file of byte habe ich wieder begraben. Einfach zu langsam.

bigg 1. Mai 2005 17:25

Re: "binäre" Dateien
 
Bei mir ist deine Routine langsamer. :mrgreen:
Hast du nur Zeilenumbrüche in deiner Test-Datei? :lol:

Phistev 1. Mai 2005 17:33

Re: "binäre" Dateien
 
Nein, (http://Phistev.united-systems.org/combined.cab, 10 MB) aber ich musste auch feststellen, dass die Performance schwankt. Ich erstelle gerade eine zweite Testdatei (2GB), um zu sehen, wie sehr Vor- und Nachbereitung (TFileStream.Create etc.) auf die Performance wirken.

bigg 1. Mai 2005 18:12

Re: "binäre" Dateien
 
Ich denke eine Funktion mit AssignFile, BlockRead, ResetFile und CloseFile sollte noch schneller sein :o
Außerdem könnte man sie vielseitger verwenden. :P


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:09 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz