Reputation: 103
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
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
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.
Upvotes: 2
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