I can only see a way to read the entire stream, and the length of each
line is not known in advance
Google just returns stuff on the textfile command readln, from my
understanding, Textfile does not offer the ability to lock a
file for reading and writing like the TFilestream does, or offers
exception handling.
Any help appreciated
Thanks in advance
> Hello,
> Is there a way to read only a line at a time using TFileStreams like the
> TextFile class ?
One alternative, if the file will fit in memory, might be to create a
TStringList and use LoadFromFile.
You might also try searching
http://www.torry.net/searchpage.htm
and
http://community.borland.com/homepages/dsp/
I got at least one likely hit on Torry.net when searching for "text file
stream".
HTH,
Harley Pebley
If your files are too large to simply load them en bloc into a TStringlist you
can try the following unit, which allows you to attach a Textfile to a stream
and then use the usual ReadLn and Read functions on it.
{== Unit StreamIO =====================================================}
{: Implements a text-file device driver that allows textfile-style I/O
on streams.
@author Dr. Peter Below
@desc Version 1.0 created 4 Januar 2001<BR>
Current revision 1.0<BR>
Last modified 4 Januar 2001<P> }
{======================================================================}
Unit StreamIO;
Interface
Uses classes;
{-- AssignStream ------------------------------------------------------}
{: Attach a stream to a Textfile to allow I/O via WriteLn/ReadLn
@Param F is the textfile to attach the stream to
@Param S is the stream
@Precondition S <> nil
@Desc The passed streams position will be set to 0 by Reset and Rewrite
and to the streams end by Append. The stream is not freed when the
textfile is closed via CloseFile and it has to stay in existence as
long as the textfile is open.
}{ Created 4.1.2001 by P. Below
-----------------------------------------------------------------------}
Procedure AssignStream( Var F: Textfile; S: TStream );
Implementation
Uses sysutils;
{-- GetDevStream ------------------------------------------------------}
{: Get the stream reference stored in the textrec userdata area
@Param F is the textfile record
@Returns the stream reference
@Postcondition result <> nil
}{ Created 4.1.2001 by P. Below
-----------------------------------------------------------------------}
Function GetDevStream( Var F: TTextRec ): TStream;
Begin { GetDevStream }
Move( F.Userdata, Result, Sizeof( Result ));
Assert( Assigned( Result ));
End; { GetDevStream }
{-- DevIn -------------------------------------------------------------}
{: Called by Read, ReadLn etc. to fill the textfiles buffer from the
device.
@Param F is the textfile to operate on
@Returns 0 (no error)
}{ Created 4.1.2001 by P. Below
-----------------------------------------------------------------------}
Function DevIn( Var F: TTextRec ): Integer;
Begin { DevIn }
Result := 0;
With F Do Begin
BufEnd := GetDevStream(F).Read( BufPtr^, BufSize );
BufPos := 0;
End; { With }
End; { DevIn }
{-- DevFlushIn --------------------------------------------------------}
{: A dummy method, flush on input does nothing.
@Param F is the textfile to operate on
@Returns 0 (no error)
}{ Created 4.1.2001 by P. Below
-----------------------------------------------------------------------}
Function DevFlushIn( Var F: TTextRec ): Integer;
Begin { DevFlushIn }
Result := 0;
End; { DevFlushIn }
{-- DevOut ------------------------------------------------------------}
{: Write the textfile buffers content to the stream. Called by Write,
WriteLn when the buffer becomes full. Also called by Flush.
@Param F is the textfile to operate on
@Returns 0 (no error)
@Raises EStreamError if the write failed for some reason.
}{ Created 4.1.2001 by P. Below
-----------------------------------------------------------------------}
Function DevOut( Var F: TTextRec ): Integer;
Begin { DevOut }
Result := 0;
With F Do
If BufPos > 0 Then Begin
GetDevStream(F).WriteBuffer( BufPtr^, BufPos );
BufPos := 0;
End; { If }
End; { DevOut }
{-- DevClose ----------------------------------------------------------}
{: Called by Closefile. Does nothing here.
@Param F is the textfile to operate on
@Returns 0 (no error)
}{ Created 4.1.2001 by P. Below
-----------------------------------------------------------------------}
Function DevClose( Var F: TTextRec ): Integer;
Begin { DevClose }
Result := 0;
End; { DevClose }
{-- DevOpen -----------------------------------------------------------}
{: Called by Reset, Rewrite, or Append to prepare the textfile for I/O
@Param F is the textfile to operate on
@Returns 0 (no error)
}{ Created 4.1.2001 by P. Below
-----------------------------------------------------------------------}
Function DevOpen( Var F: TTextRec ): Integer;
Begin { DevOpen }
Result := 0;
With F Do Begin
Case Mode Of
fmInput: Begin { Reset }
InOutFunc := @DevIn;
FlushFunc := @DevFlushIn;
BufPos := 0;
BufEnd := 0;
GetDevStream( F ).Position := 0;
End; { Case fmInput }
fmOutput: Begin { Rewrite }
InOutFunc := @DevOut;
FlushFunc := @DevOut;
BufPos := 0;
BufEnd := 0;
GetDevStream( F ).Position := 0;
End; { Case fmOutput }
fmInOut: Begin { Append }
Mode := fmOutput;
DevOpen( F );
GetDevStream(F).Seek( 0, soFromEnd );
End; { Case fmInOut }
End; { Case }
End; { With }
End; { DevOpen }
Procedure AssignStream( Var F: Textfile; S: TStream );
Begin { AssignStream }
Assert( Assigned( S ));
With TTextRec(F) Do Begin
Mode := fmClosed;
BufSize := SizeOf(Buffer);
BufPtr := @Buffer;
OpenFunc := @DevOpen;
CloseFunc := @DevClose;
Name[0] := #0;
{ Store stream reference into Userdata area }
Move( S, Userdata, Sizeof(S));
End; { With }
End; { AssignStream }
End { StreamIO }.
--
Peter Below (TeamB)
Use the newsgroup archives :
http://www.mers.com/searchsite.html
http://www.tamaracka.com/search.htm
http://groups.google.com
http://www.prolix.be
I just saw the other post about tab files, which is what I really wanted to
do, I wanted to know if the
Streams classes allowed to read a line at a time, so I could pass the line
and extract the tokens a line at a time or as and when required, but I am
going to take a closer look at this as well, it is brilliant, TFileStreams
that can mimic useful methods of the equally useful text file class.
Thanks also to Harley for his help, though I have been unable to find the
post he found as yet, I normally use BDN and about.com, Tori site is
excellent, but afaics it has useful apps to download from it, but thanks I
will look at it in more detail.
Take a look at Julian Bucknall's article on extending TStream classes
in Issue 70 of The Delphi Magazine - source code from
http://www.thedelphimagazine.com/disks/dmag70.zip
This article describes several classes which are wrappers around
existing TStream objects to provide additional functionality. The
TaaReadTextFilter class provides the ReadLn functionality that you
require.
John Leavey