用tfilestreamdelphi读取行
如何使用某些行TFileStream读取文件。我读的行有数百万个文件。所以我想在我只会使用的记忆中玩 例如:用tfilestreamdelphi读取行,delphi,tfilestream,Delphi,Tfilestream,如何使用某些行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,但它看起来很慢。
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中最后一行的函数。您可以使用TFileStream类打开一个文件进行读取,如下所示
FileStream := TFileStream.Create( 'MyBigTextFile.txt', fmOpenRead)
FileStream.Free
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;
TFileStream不是引用计数对象,所以请确保在完成后释放它,就像这样
FileStream := TFileStream.Create( 'MyBigTextFile.txt', fmOpenRead)
FileStream.Free
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;
从这里开始,我将假设您的文件的字符编码是UTF-8,并且行尾终止是MS样式。如果没有,请相应调整,或更新您的问题
您可以读取UTF-8字符的单个代码单元(与读取单个字符不同),如下所示:
你可以读一行这样的文字
FileStream := TFileStream.Create( 'MyBigTextFile.txt', fmOpenRead)
FileStream.Free
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;
您可以使用传统的文件操作。 要真正快速,您必须确保每一行中的字节数相同 Blockread、BlockWrite、Seek是您可以查看的关键字
由于TFileStream,Sean propose的代码速度很慢。如David所述。但是,如果您使用TMemoryStream而不是TFileStream,那么慢速Stream.Read就不那么重要了。在这种情况下,字符串操作占用了大部分时间 如果您稍微更改代码,速度将提高2倍:
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;
函数ReadLine(流:TStream;变量行:string):布尔;
变量
ch:AnsiChar;
StartPos,LineLen:整数;
开始
结果:=假;
StartPos:=流位置;
ch:=#0;
而(Stream.Read(ch,1)=1)和(ch#13)do;
LineLen:=流位置-起始位置;
流位置:=StartPos;
设置字符串(直线、零、直线长度);
ReadBuffer(第[1]行,第len行);
如果ch=#13,则
开始
结果:=真;
如果(Stream.Read(ch,1)=1)和(ch#10),则
Stream.Seek(-1,soCurrent)//如果不是LF字符,则未读它。
结束
结束;
对于一个大文件来说,这将是非常缓慢的。一次调用ReadFile 1字节会带来伤害。实际上是的。O/S缓冲区,但在调用ReadFile时有很大的开销。我在这里的一个答案详细说明了这一点。它是否有效在很大程度上取决于上下文和您的期望。OP可以很容易地进行调整并分块阅读。但是上面的解决方案是OP获得基本想法所需要的全部。为了提高效率,有无数的变化。但是这些都是上下文敏感的,这种优化最好留给OP来完成。如果要阅读很多行,那么就需要进行优化。我的答案是:谢谢你的答复。在delphi 7中,给出了错误代码Stream.Seek(soCurrent,-1)有一个重载版本的'Seek',可以用这些参数调用。格式可能是+1的副本,以抵消向下表决。鉴于Andre对我的评论“您的行大小是否固定?”的回复,BlockRead()/Seek()选项是可行的。