André
André

Reputation: 103

Read Line with TFileStream delphi

How do I read file using certain lines TFileStream. I read lines which has millions of files. So I want to play in memory that I will only use

Example:

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

I read the line 2 to 4

I used a function TextFile, but it seems slow. Just found a function that reads the last line in TFileStream.

Upvotes: 4

Views: 30259

Answers (3)

nfc1
nfc1

Reputation: 190

Code Sean propose is slow because of the TFileStream.Read as David explained. But in case you use TMemoryStream instead of TFileStream, the slow Stream.Read is not so important. In such a case the string operations take most of the time.

If you slightly change the code the speed is cca 2 x higher:

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;

Upvotes: 0

Ali Avcı
Ali Avcı

Reputation: 870

You may make use of traditional file operations. To be real fast you have to be sure that each line has the same amount of bytes in it.

Blockread, BlockWrite, Seek are the keywords you may look at.

Sample page for BlockRead

Sample page for Seek

Upvotes: 2

Sean B. Durkin
Sean B. Durkin

Reputation: 12729

You can open a file for reading with the TFileStream class like so ...

FileStream := TFileStream.Create( 'MyBigTextFile.txt', fmOpenRead)

TFileStream is not a reference counted object, so be sure and release it when you are done, like so ...

FileStream.Free

From here-on in, I will assume that your file's character encoding is UTF-8 and that the end-of-line termination is MS style. If not, please adjust accordingly, or update your question.

You can read a single code unit of a UTF-8 character (not the same thing as reading a single character) like so:

var ch: ansichar;
FileStream.ReadBuffer( ch, 1);

You can read a line of text like so ...

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;

To read lines 2, 3 and 4, assuming position is at 0 ...

ReadLine( Stream, Line1);
ReadLine( Stream, Line2);
ReadLine( Stream, Line3);
ReadLine( Stream, Line4);

Upvotes: 13

Related Questions