I always wanted to find a solution to this problem, so I wrote one that is part of the JvCsvDataSet. My problems:
- I want to read a file that may have CR, CR + LF, or just the ends of LF.
- I want something like ReadLn, but which is really flexible to point # 1 and doesn't have well-known ReadLn issues. Thus, Ancient Pascal had a Textfile type and a ReadLn procedure. A modern class equivalent is needed.
- I would like it to be a streaming object, so I can read line by line rather than load all of my megabyte megabyte 3.7 gigabytes into memory. In addition, I want the position to be an Int64 type, and I want to be able to handle very large files (> 2 gb).
- I want this to work in Delphi 7, as well as in Delphi XE2 and everything in between.
- I wanted it to be very fast. So I spent some time optimizing the performance of reading blocks and parsing.
So here is what you could write if you want to do this:
procedure TForm1.Button1Click(Sender: TObject); var ts:TTextStream; s:String; begin ts := TTextStream.Create('c:\temp\test.txt', fm_OpenReadShared); try while not ts.Eof do begin s := ts.ReadLine; doSomethingWith(s); end; finally ts.Free; end; end;
Good. Does it look easy? It. And it even has a file mode flag (note the readable parameter?). Now all you need is the Teh Codez For TTextStream, which are here:
unit textStreamUnit; {$M+} {$R-} { textStreamUnit This code is based on some of the content of the JvCsvDataSet written by Warren Postma, and others, licensed under MOZILLA Public License. } interface uses Windows, Classes, SysUtils; const cQuote = #34; cLf = #10; cCR = #13; { File stream mode flags used in TTextStream } { Significant 16 bits are reserved for standard file stream mode bits. } { Standard system values like fmOpenReadWrite are in SysUtils. } fm_APPEND_FLAG = $20000; fm_REWRITE_FLAG = $10000; { combined Friendly mode flag values } fm_Append = fmOpenReadWrite or fm_APPEND_FLAG; fm_OpenReadShared = fmOpenRead or fmShareDenyWrite; fm_OpenRewrite = fmOpenReadWrite or fm_REWRITE_FLAG; fm_Truncate = fmCreate or fm_REWRITE_FLAG; fm_Rewrite = fmCreate or fm_REWRITE_FLAG; TextStreamReadChunkSize = 8192;
source share