用tfilestreamdelphi读取行

用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,但它看起来很慢。

如何使用某些行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中最后一行的函数。

您可以使用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()选项是可行的。