如何使用某些行TFileStream读取文件。我读了有数百万个文件的行。所以我想在内存中玩,我只会使用
示例:
Line 1: 00 00 00 00 00 00 00 00
Line 2: 00 00 00 00 00 00 00 00
Line 3: 00 00 00 00 00 00 00 00
Line 4: 00 00 00 00 00 00 00 00
Line 5: 00 00 00 00 00 00 00 00
我读了2到4行
我使用了一个TextFile函数,但看起来很慢。刚刚找到一个读取TFileStream中最后一行的函数。
答案 0 :(得分:8)
您可以使用TFileStream类打开文件进行读取,如此...
FileStream := TFileStream.Create( 'MyBigTextFile.txt', fmOpenRead)
TFileStream不是引用计数对象,所以请确保在完成后释放它,就像这样......
FileStream.Free
从这里开始,我将假设您的文件的字符编码是UTF-8,并且行尾终止是MS样式。如果没有,请相应调整,或更新您的问题。
您可以读取UTF-8字符的单个代码单元(与读取单个字符的内容不同),如下所示:
var ch: ansichar;
FileStream.ReadBuffer( ch, 1);
您可以阅读一行文字......
function ReadLine( var Stream: TStream; var Line: string): boolean;
var
RawLine: UTF8String;
ch: AnsiChar;
begin
result := False;
ch := #0;
while (Stream.Read( ch, 1) = 1) and (ch <> #13) do
begin
result := True;
RawLine := RawLine + ch
end;
Line := RawLine;
if ch = #13 then
begin
result := True;
if (Stream.Read( ch, 1) = 1) and (ch <> #10) then
Stream.Seek(-1, soCurrent) // unread it if not LF character.
end
end;
要读取第2,3和4行,假设位置为0 ...
ReadLine( Stream, Line1);
ReadLine( Stream, Line2);
ReadLine( Stream, Line3);
ReadLine( Stream, Line4);
答案 1 :(得分:2)
您可以使用传统的文件操作。 要真正快速,你必须确保每一行都有相同的字节数。
Blockread,BlockWrite,Seek是您可以查看的关键字。
答案 2 :(得分:0)
Code Sean建议很慢,因为大卫解释说TFileStream.Read。但是如果你使用TMemoryStream而不是TFileStream,那么缓慢的Stream.Read就不那么重要了。在这种情况下,字符串操作占用大部分时间。
如果您稍微更改代码,则速度为cca 2 x更高:
function ReadLine(Stream: TStream; var Line: string): boolean;
var
ch: AnsiChar;
StartPos, LineLen: integer;
begin
result := False;
StartPos := Stream.Position;
ch := #0;
while (Stream.Read( ch, 1) = 1) and (ch <> #13) do;
LineLen := Stream.Position - StartPos;
Stream.Position := StartPos;
SetString(Line, NIL, LineLen);
Stream.ReadBuffer(Line[1], LineLen);
if ch = #13 then
begin
result := True;
if (Stream.Read( ch, 1) = 1) and (ch <> #10) then
Stream.Seek(-1, soCurrent) // unread it if not LF character.
end
end;