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
47 procedure checkandread;
\r
52 constructor treadtxt.create(asourcestream: tstream; adestroysourcestream:boolean);
\r
55 sourcestream := asourcestream;
\r
56 destroysourcestream := adestroysourcestream;
\r
58 //if sourcestream.Position >= sourcestream.size then fileeof := true;
\r
59 bufpointer := bufsize;
\r
62 constructor treadtxt.createf(filename: string);
\r
64 create(tfilestream.create(filename,fmOpenRead),true);
\r
68 procedure treadtxt.checkandread;
\r
70 if bufpointer >= numread then begin
\r
71 numread := sourcestream.read(buf,bufsize);
\r
73 if numread = 0 then fileeof := true;
\r
78 function treadtxt.readline;
\r
88 {core search loop begin}
\r
90 for a := bufpointer to b do begin
\r
92 if (c = 10) or (c = 13) then begin
\r
97 {core search loop end}
\r
99 c := length(result);
\r
100 if (d = -1) then begin
\r
101 {ran out of buffer before end of line}
\r
102 b := numread-bufpointer;
\r
103 setlength(result,c+b);
\r
104 move(buf[bufpointer],result[c+1],b);
\r
105 bufpointer := numread;
\r
106 if fileeof then begin
\r
107 {we reached the end of the file, return what we have}
\r
108 reachedeof := true;
\r
113 preveol := currenteol;
\r
114 currenteol := buf[d];
\r
116 {end of line before end of buffer}
\r
117 if (currenteol = 10) and (preveol = 13) then begin
\r
118 {it's the second EOL char of a DOS line ending, don't cause a line}
\r
120 eoltype := eoltype_crlf;
\r
122 if eoltype = eoltype_none then begin
\r
123 if (currenteol = 10) then eoltype := eoltype_lf else eoltype := eoltype_cr;
\r
126 setlength(result,c+b);
\r
127 move(buf[bufpointer],result[c+1],b);
\r
131 if fileeof then begin
\r
132 if (bufpointer >= numread) then reachedeof := true;
\r
133 if (currenteol = 13) and (bufpointer = numread-1) then if (buf[bufpointer] = 10) then reachedeof := true;
\r
142 function treadtxt.eof:boolean;
\r
145 result := ((bufpointer >= numread) and fileeof) or reachedeof;
\r
148 destructor treadtxt.destroy;
\r
150 if destroysourcestream then if assigned(sourcestream) then sourcestream.destroy;
\r