Mega Code Archive

 
Categories / Delphi / Files
 

How to read a string from a text file at a certain line number

Title: How to read a string from a text file at a certain line number uses SysUtils, Classes; function GrabLine(const AFileName: string; ALine: Integer): string; var fs: TFileStream; buf: packed array[0..4095] of Char; bufRead: Integer; bufPos: PChar; lineStart: PChar; tmp: string; begin fs := TFileStream.Create(AFileName, fmOpenRead); try Dec(ALine); bufRead := 0; bufPos := nil; { read the first line specially } if ALine = 0 then begin bufRead := fs.Read(buf, SizeOf(buf)); if bufRead = 0 then raise Exception.Create('Line not found'); bufPos := buf; end else while ALine 0 do begin { read in a buffer } bufRead := fs.Read(buf, SizeOf(buf)); if bufRead = 0 then raise Exception.Create('Line not found'); bufPos := buf; while (bufRead 0) and (ALine 0) do begin if bufPos^ = #10 then Dec(ALine); Inc(bufPos); Dec(bufRead); end; end; { Found the beginning of the line at bufPos... scan for end. 2 cases: 1) we'll find it before the end of this buffer 2) it'll go beyond this buffer and into n more buffers } lineStart := bufPos; while (bufRead 0) and (bufPos^ #10) do begin Inc(bufPos); Dec(bufRead); end; { if bufRead is positive, we'll have found the end and we can leave. } SetString(Result, lineStart, bufPos - lineStart); { determine if there are more buffers to process } while bufRead = 0 do begin bufRead := fs.Read(buf, SizeOf(buf)); lineStart := buf; bufPos := buf; while (bufRead 0) and (bufPos^ #10) do begin Inc(bufPos); Dec(bufRead); end; SetString(tmp, lineStart, bufPos - lineStart); Result := Result + tmp; end; finally fs.Free; end; end; function GrabLine2(const s: string; ALine: Integer): string; var sl: TStringList; begin sl := TStringList.Create; try sl.LoadFromFile(s); Result := sl[ALine - 1]; // index off by one finally sl.Free; end; end; begin Writeln(GrabLine(ParamStr(1), StrToInt(ParamStr(2)))); Writeln(GrabLine2(ParamStr(1), StrToInt(ParamStr(2)))); end. Call it like ??getline testfile.txt 20000??, depending on what you call the .pas (or .dpr) file. For large (i.e. tens of megabytes) files, the (rather complex) scanning function easily beats the memory expensive StringList version.