2013-03-27 40 views
4

我有一個二進制文件(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; 
+4

哪部分代碼慢?你表演過嗎?你怎麼知道它很慢?它是什麼速度,你期望能達到什麼? – 2013-03-27 14:58:47

+5

顯而易見讀寫文件char-by-char的速度很慢。至少通過更大的塊將數據提取到緩衝區中(請參閱BlockRead)。 – OnTheFly 2013-03-27 15:12:42

+0

@DavidHeffernan,是的,它正在搜索序列位置的部分很慢。現在大約需要15秒才能完成5個文件,我希望最多隻需1-3秒。如果我評論它,並將StartIndex設置爲9999,那麼它是即時的。我認爲這並不是最好的解決方案來逐字節讀取所有文件內容作爲字符+將其複製到字符串。 – AlexP11223 2013-03-27 15:23:08

回答

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)

代碼可以進一步優化,只讀取文件的一部分,並搜索,直到找到目標爲止。您可能能夠避免以這種方式讀取整個文件。不過,我懷疑這些變化會帶來足夠的差異。

6

看到這個答案:Fast read/write from file in delphi

某些選項:

要搜索文件緩衝區,請參閱Best way to find position in the Stream where given byte sequence starts - 一個答案提到Boyer-Moore algorithm用於快速檢測字節序列。

+0

我只需讀取一個塊,掃描它的第一個字節,然後評估其餘部分,並在適當時短路。處理出現在塊末尾的序列的開始似乎是這裏最明顯的邊緣條件。 – 2013-03-27 17:19:08