我從xml文件讀取UTF8內容,然後需要保存並按需重新加載。我從AssignFile/Writeln/Readln轉換到由David Heffernan創建的緩衝流:Buffered files (for faster disk access)如何將Readln替換爲ReadLn的緩衝流版本?
我有簡單的新的WriteLn和ReadLn程序,WriteLn可以工作,但是我無法讓ReadLn工作。
我對ReadLn概念是過程:
- 讀取緩衝
- 行查找打破
- 從PrevPos獲取文本到CurrPos-1 緩衝的
- 保存其餘添加到第一線next讀緩衝區
新寫入程序:
{ * New WriteLn * }
procedure TForm1.Button2Click(Sender: TObject);
var FileOut: TWriteCachedFileStream;
vText: string;
vUTF8Text: RawByteString;
begin
FileOut := TWriteCachedFileStream.Create('c:\tmp\file.txt');
try
vText := 'Delphi';
vUTF8Text := Utf8Encode(vText + sLineBreak);
FileOut.WriteBuffer(PAnsichar(vUTF8Text)^, Length(vUTF8Text));
vText := 'VB源碼';
vUTF8Text := Utf8Encode(vText + sLineBreak);
FileOut.WriteBuffer(PAnsichar(vUTF8Text)^, Length(vUTF8Text));
vText := 'Java源碼';
vUTF8Text := Utf8Encode(vText + sLineBreak);
FileOut.WriteBuffer(PAnsichar(vUTF8Text)^, Length(vUTF8Text));
finally
FileOut.Free;
end;
end;
但是由於讀取失敗,無法讀取文件。發生在錯誤讀取TReadOnlyCachedFileStream的功能:
錯誤說:
"Project Project1.exe raised exception class $C0000005 with message 'access violation at 0x004069ca: write of address 0x00000010'."
function TReadOnlyCachedFileStream.Read(var Buffer; Count: Longint): Longint;
begin
...
Move(CachePtr^, BufferPtr^, NumOfBytesToCopy); { <- Error occurs here }
...
end;
這裏是我的ReadLn程序 - 不工作,因爲我無法通過的錯誤提示:
{ * New ReadLn * }
procedure TForm1.Button3Click(Sender: TObject);
var FileIn: TReadOnlyCachedFileStream;
vLinesCounter, vCurrPos, vPrevPos: integer;
vBuffer: TBytes;
vUTF8Text, vPrevUTF8Text: string;
vFilesize,vBytesRead,vNumberOfBytes: Int64;
vCh: Char;
begin
vLinesCounter := 0;
FileIn := TReadOnlyCachedFileStream.Create('c:\tmp\file.txt');
try
vFilesize := FileIn.Size;
while FileIn.Position < vFilesize do
begin
vBytesRead:=FileIn.Read(vBuffer, 65536);
vNumberOfBytes := vNumberOfBytes + vBytesRead;
{1. Find Line break
2. Get Text from PrevPos to CurrPos-1
3. Save rest of buffer to add to first line of next Read buffer}
vCurrPos := 0; vPrevPos := 0;
while vCurrPos < vBytesRead do
begin
vCh:=Chr(vBuffer[vCurrPos]);
if (vCh = #13) Or (vCh = #10) then { is New line }
begin
if vPrevUTF8Text <> '' then
vUTF8Text := vPrevUTF8Text + TEncoding.UTF8.GetString(vBuffer, vPrevPos, vCurrPos - 1) { Add previous text that was not separet line}
else
vUTF8Text := TEncoding.UTF8.GetString(vBuffer, vPrevPos, vCurrPos - 1);
vPrevPos := vCurrPos; { Save Pos for next line }
Inc(vLinesCounter);
Memo1.Lines.Add(vUTF8Text);
end;
end;
{ save rest of text as start of next line }
if vCurrPos < Length(vBuffer) then
vPrevUTF8Text := TEncoding.UTF8.GetString(vBuffer, vPrevPos, vCurrPos - 1);
end;
finally
FileIn.Free
end;
Memo1.Lines.Add('Lines read: '+IntToStr(vLinesCounter));
end;
這個錯誤是因爲您的來電閱讀是錯誤的。你沒有分配一個緩衝區,即使你正在讀入指向緩衝區的指針,而不是緩衝區本身。在調用Read時,用SetLength(憑證,65536)分配緩衝區並傳遞指針(vBuffer)^。 –
除此之外,Memo1.Lines.LoadFromFile真的很慢嗎? –
Memo1這裏僅僅用於驗證正在讀取的內容,而不是用作主文件加載方法。好吧,現在它可以用SetLength和指針(vBuffer)^'。 –