我有一个二进制文件(2.5 MB),我想找到这个字节序列的位置:CD 09 D9 F5。然后我想在这个位置后写一些数据,并用零覆盖旧数据(4 KB)。
以下是我现在的表现,但有点慢。
ProcessFile(dataToWrite: string);
var
fileContent: string;
f: file of char;
c: char;
n, i, startIndex, endIndex: integer;
begin
AssignFile(f, 'file.bin');
reset(f);
n := FileSize(f);
while n > 0 do
begin
Read(f, c);
fileContent := fileContent + c;
dec(n);
end;
CloseFile(f);
startindex := Pos(Char($CD)+Char($09)+Char($D9)+Char($F5), fileContent) + 4;
endIndex := startIndex + 4088;
Seek(f, startIndex);
for i := 1 to length(dataToWrite) do
Write(f, dataToWrite[i]);
c := #0;
while (i < endIndex) do
begin
Write(f, c); inc(i);
end;
CloseFile(f);
end;
答案 0 :(得分:6)
请参阅此答案:Fast read/write from file in delphi
有些选择是:
要搜索文件缓冲区,请参阅Best way to find position in the Stream where given byte sequence starts - 一个答案提及Boyer-Moore algorithm以快速检测字节序列。
答案 1 :(得分:3)
将整个文件读入字符串的代码非常浪费。 Pascal I / O使用缓冲,所以我不认为这是逐字节方面的特别之处。虽然一个大的阅读会更好。主要问题是字符串连接和连接字符串所需的极端堆分配需求,一次一个字符。
我会这样做:
function LoadFileIntoString(const FileName: string): string;
var
Stream: TFileStream;
begin
Stream := TFileStream.Create(FileName, fmOpenRead);
try
SetLength(Result, Stream.Size);//one single heap allocation
Stream.ReadBuffer(Pointer(Result)^, Length(Result));
finally
Stream.Free;
end;
end;
仅此一点应该会有很大的不同。在编写文件时,类似使用字符串会快得多。我没有试图破译你的代码的写作部分。再次编写新数据和零块应该尽可能少地单独写入。
如果您发现需要读取或写入非常小的块到文件,那么我会向您提供我的缓冲文件流:Buffered files (for faster disk access)。
可以进一步优化代码以仅读取文件的一部分,并搜索直到找到目标。您可以避免以这种方式读取整个文件。但是,我怀疑这些变化会产生足够的差异。