3

特定の行 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 の最後の行を読み取る関数が見つかりました。

4

3 に答える 3

12

次のように、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;

位置が 0 であると仮定して、2 行目、3 行目、4 行目を読み取るには ...

ReadLine( Stream, Line1);
ReadLine( Stream, Line2);
ReadLine( Stream, Line3);
ReadLine( Stream, Line4);
于 2012-07-22T07:14:33.413 に答える
2

従来のファイル操作を利用できます。本当に高速にするには、各行に同じ量のバイトが含まれていることを確認する必要があります。

Blockread、BlockWrite、Seek がキーワードです。

BlockRead のサンプルページ

Seekのサンプルページ

于 2012-07-23T08:51:42.227 に答える
0

David が説明したように、Sean が提案するコードは TFileStream.Read のために遅いです。ただし、TFileStream の代わりに TMemoryStream を使用する場合、遅い 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;
于 2016-02-13T01:33:23.783 に答える