1 { Copyright (C) 2009 Bas Steendijk and Peter Green
\r
2 For conditions of distribution and use, see copyright notice in zlib_license.txt
\r
3 which is included in the package
\r
4 ----------------------------------------------------------------------------- }
\r
14 this can be used to read a text file exposed as a tstream line by line.
\r
15 automatic handling of CR, LF, and CRLF line endings, and readout of detected line ending type.
\r
16 fast: 1.5-2 times faster than textfile readln in tests.
\r
30 treadtxt=class(tobject)
\r
32 sourcestream:tstream;
\r
33 destroysourcestream:boolean;
\r
34 constructor create(asourcestream: tstream; adestroysourcestream:boolean);
\r
35 constructor createf(filename : string);
\r
37 function readline:ansistring;
\r
38 function eof:boolean;
\r
39 destructor destroy; override;
\r
41 buf:array[0..bufsize-1] of byte;
\r
44 currenteol,preveol:integer;
\r
45 fileeof,reachedeof:boolean;
\r
51 constructor treadtxt.create(asourcestream: tstream; adestroysourcestream:boolean);
\r
54 sourcestream := asourcestream;
\r
55 destroysourcestream := adestroysourcestream;
\r
57 if sourcestream.Position >= sourcestream.size then fileeof := true;
\r
58 bufpointer := bufsize;
\r
59 destroysourcestream := false;
\r
62 constructor treadtxt.createf(filename: string);
\r
64 create(tfilestream.create(filename,fmOpenRead),true);
\r
68 function treadtxt.readline;
\r
75 if bufpointer >= bufsize then begin
\r
76 numread := sourcestream.read(buf,bufsize);
\r
78 if sourcestream.Position >= sourcestream.size then fileeof := true;
\r
82 {core search loop begin}
\r
84 for a := bufpointer to b do begin
\r
86 if (c = 10) or (c = 13) then begin
\r
91 {core search loop end}
\r
93 c := length(result);
\r
94 if (d = -1) then begin
\r
95 {ran out of buffer before end of line}
\r
96 b := numread-bufpointer;
\r
97 setlength(result,c+b);
\r
98 move(buf[bufpointer],result[c+1],b);
\r
99 bufpointer := numread;
\r
100 if numread < bufsize then begin
\r
101 reachedeof := true;
\r
106 preveol := currenteol;
\r
107 currenteol := buf[d];
\r
109 {end of line before end of buffer}
\r
110 if (currenteol = 10) and (preveol = 13) then begin
\r
111 {it's the second EOL char of a DOS line ending, don't cause a line}
\r
113 eoltype := eoltype_crlf;
\r
115 if eoltype = eoltype_none then begin
\r
116 if (currenteol = 10) then eoltype := eoltype_lf else eoltype := eoltype_cr;
\r
119 setlength(result,c+b);
\r
120 move(buf[bufpointer],result[c+1],b);
\r
124 if fileeof then begin
\r
125 if (bufpointer >= numread) then reachedeof := true;
\r
126 if (currenteol = 13) and (bufpointer = numread-1) then if (buf[bufpointer] = 10) then reachedeof := true;
\r
135 function treadtxt.eof:boolean;
\r
138 result := ((bufpointer >= bufsize) and fileeof) or reachedeof;
\r
141 destructor treadtxt.destroy;
\r
143 if destroysourcestream then if assigned(sourcestream) then sourcestream.destroy;
\r