2015-04-06 132 views
0

我在循環中使用TFileStream.Read讀取文本文件,但我發現最後一部分沒有被讀入緩衝區 - 雖然總字節數讀取等於文件大小。TFileStream.Read沒有讀取文件的最後部分

這是我的代碼:

procedure TForm1.DoImport; 
var 
    f: String; 
    fs: TFileStream; 
    r, c: Integer; 
    buf: TBytes; 

const 
    bufsiz = 16384; 
begin 
    SetLength(buf, bufsiz); 

    f := 'C:\Report\Claims\Claims.csv'; 

    fs := TFileStream.Create(f, fmOpenRead); 
    try 
    c := 0; 
    repeat 

     r := fs.Read(buf, bufsiz); 

     Inc(c, r); 

    until (r <> bufsiz); 

    showmessage('Done. ' + IntToStr(c)); // <-- c equals to filesize !! 

    Memo1.Text := StringOf(buf); // <-- but the memo does not show the last chunk of the file 

    finally 
    fs.Free; 
    end; 

end; 

在年底,TMemo不包含該文件的最後一個塊,但第二到最後一個大塊。我的代碼有問題嗎?

在此先感謝!

+0

實際上只有文件的最後部分應該是可見的。你不斷讀入同一個緩衝區buf並覆蓋舊的內容。 – gabr 2015-04-06 12:23:34

+0

@RawN:所以我應該在調用Read之前有一個FillChar(buf [Low(buf)],Length(buf),0)? – 2015-04-06 12:24:07

+0

@gabr:是的,我只想要文件的最後部分。我現在只是測試代碼。但它沒有顯示最後一部分......它顯示了接下來的最後一部分。 – 2015-04-06 12:25:13

回答

1

該緩衝區的開始包含文件的最後一個塊。但之後就是前一個塊的內容,因爲你從未清除緩衝區。所以你認爲你的備忘錄包含了前面的塊,但它是兩者的混合體。

您可以使用複製功能來添加一部分緩衝區。

Memo1.Text := StringOf(Copy(buf, 0, r)); // r is the number of bytes to copy 

閱讀文本文件一個更好的辦法是使用TStringListTStringReader。這些將會處理文件編碼(Ansi,UTF8,...)我通常更喜歡TStringList,因爲我在TStringReader中遇到了一些問題。

+0

我發現「ZeroMemory(buf,bufsiz);」就在「r:= fs.Read(buf,bufsiz);」之前似乎在做詭計! – 2015-04-06 13:21:05

+0

是的,這適用於備忘錄,因爲它在末尾修剪零字節。如果你做了'mystring:= stringof(buf);'你會在最後得到一個#0字節的字符串,這可能不是你想要的。 – 2015-04-06 13:24:26