![]() |
"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; |
Re: "binäre" Dateien
würde ich hierher geben "Neuen Beitrag zur Code-Library hinzufügen" ist ja wichtig
|
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 |
Re: "binäre" Dateien
Zitat:
PS: Wenn die Mods nichts dagegen haben, kann der Thread verschoben werden.^^ |
Re: "binäre" Dateien
Zitat:
Danke für diesen Hinweis :zwinker: |
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. |
Re: "binäre" Dateien
Liste der Anhänge anzeigen (Anzahl: 1)
Wenn man das Set durch eine Abfrage wie
Delphi-Quellcode:
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...
if (Buffer[f] < 32) and (Buffer[f] <> 9) and (Buffer[f] <> 10) and (Buffer[f] <> 13) then
/edit: Das mit file of byte habe ich wieder begraben. Einfach zu langsam. |
Re: "binäre" Dateien
Bei mir ist deine Routine langsamer. :mrgreen:
Hast du nur Zeilenumbrüche in deiner Test-Datei? :lol: |
Re: "binäre" Dateien
Nein, (
![]() |
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. |
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