Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Text Files and Streams

2,484 views
Skip to first unread message

Mark Genovese

unread,
Jan 3, 2001, 3:13:25 PM1/3/01
to
I would like to use a stream to read and write text files, much like the way
that ReadLn( ) and WriteLn( ) work. Does anyone know an easy way to do
this? I have seen several postings talking about streaming various types of
data. I don't need anything fancy. I just want to perform ReadLn and
WriteLn equivalent procedures with a stream (TFileStream) doing the work
underneath.

Thanks in advance,

Mark


Glynn Owen

unread,
Jan 3, 2001, 3:41:46 PM1/3/01
to
Why not just open the file as a text file and use Readln and Writeln?
Glynn

Mark Genovese

unread,
Jan 3, 2001, 3:49:33 PM1/3/01
to
I am currently using a stream to read a text file. I read the entire
contents using a CopyFrom method. I now need to look at only the first line
(up to CR/LF) of the file. I need a simple way of doing this. The streams
do simplify a significant chunk of my program. I don't want to scrap using
them if I don't have to.
"Glynn Owen" <gl...@gtstrans.com> wrote in message
news:3A538E8A...@gtstrans.com...

Per-Eric Larsson

unread,
Jan 3, 2001, 4:30:38 PM1/3/01
to
You could send it to a TStrings
TStrings.LoadFromStream(.);
The First line would be at TStrings[0] !

/per-eric

Jack Sudarev

unread,
Jan 3, 2001, 5:43:29 PM1/3/01
to
Mark Genovese <mgen...@vtechnologies.com> wrote in message
news:9303b4$ru...@bornews.inprise.com...

> I am currently using a stream to read a text file. I read the entire
> contents using a CopyFrom method. I now need to look at only the first line
> (up to CR/LF) of the file. I need a simple way of doing this. The streams
> do simplify a significant chunk of my program. I don't want to scrap using
> them if I don't have to.
..
Mark,
you might want to do smth like this:

var
AStringList: TStringList;
begin
AStringList := TStringList.Create;
try
AStringList.LoadFromFile('c:\autoexec.bat');
ShowMessage('The first line is: "' + AStringList[0] + '"');
finally
AStringList.Free;
end;
end;

Regards,

Jack Sudarev.

Ralph Friedman (TeamB)

unread,
Jan 4, 2001, 5:54:02 AM1/4/01
to
Mark Genovese,

in message <93017b$dt...@bornews.inprise.com> you wrote:
> data. I don't need anything fancy. I just want to perform ReadLn and
> WriteLn equivalent procedures with a stream (TFileStream) doing the work
> underneath.
>

if your files aren't too big, you can use the LoadFromStream method of
TStringList to have it do the work for you. The downside is that it means
having 2 copies of the file.

--
Regards
Ralph (TeamB)
===

Mark Genovese

unread,
Jan 4, 2001, 8:33:34 AM1/4/01
to
Per-Eric,

Thank you for your suggestion. It seems to be the consensus best way to
tackle my problem.

Mark

"Per-Eric Larsson" <per-eric...@home.se> wrote in message
news:3A5399FE...@home.se...

Mark Genovese

unread,
Jan 4, 2001, 8:31:45 AM1/4/01
to
Ralph,

Thank you very much for your suggestion. I will give this a try.

Mark

"Ralph Friedman (TeamB)" <ralphf...@email.com> wrote in message
news:VA.000003b...@della.garlin...

Mark Genovese

unread,
Jan 4, 2001, 8:34:12 AM1/4/01
to
Jack,

Thank you for your suggestion. I am going to implement it today.

Mark

"Jack Sudarev" <satoriD...@hotmail.com> wrote in message
news:930a10$ru...@bornews.inprise.com...

Peter Below (TeamB)

unread,
Jan 4, 2001, 11:20:29 AM1/4/01
to
In article <93017b$dt...@bornews.inprise.com>, Mark Genovese wrote:
> I would like to use a stream to read and write text files, much like the way
> that ReadLn( ) and WriteLn( ) work. Does anyone know an easy way to do
> this?

Mark,

there is a little-known but utterly cool feature in Borlands Pascal (since TP
1.0 i think) that allows one to implement textfile-style IO on about any kind
of data stream: text-file device drivers. Using the unit below you can attach
a stream to a Textfile variable and then use Write/WriteLn/Read/ReadLn as
usual. Has only be superficially tested!

{== 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
stream.
@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) 10011...@compuserve.com)
No e-mail responses, please, unless explicitly requested!
Note: Till Feb.2001 i will only visit the groups on weekends, so be patient
if i don't reply immediately.

Jim McKay

unread,
Jan 17, 2001, 12:29:06 PM1/17/01
to

"Peter Below (TeamB)" wrote:
>
> In article <93017b$dt...@bornews.inprise.com>, Mark Genovese wrote:
> > I would like to use a stream to read and write text files, much like the way
> > that ReadLn( ) and WriteLn( ) work. Does anyone know an easy way to do
> > this?
>
> Mark,
>
> there is a little-known but utterly cool feature in Borlands Pascal (since TP
> 1.0 i think) that allows one to implement textfile-style IO on about any kind
> of data stream: text-file device drivers. Using the unit below you can attach
> a stream to a Textfile variable and then use Write/WriteLn/Read/ReadLn as
> usual. Has only be superficially tested!

Peter,
I have ended up doing something very similar to what you've posted
here for some other purposes. (found your post on deja).

At the risk of being accused of multi post (AssignFile & TextRec: 1/16/2001),
here goes:

I'm confused as to typing of TTextRec.UserData as byte array, and also
proper use of this record field. I want to use it as pointer to object,
and it seems to work OK. However, it's typing suggests it's used
internally (by Delphi?) for purposes other than pointer, and I'm concerned
that my use as stated may ursurp a process that I'm not aware of.
(hope I'm making myself clear).
I asked about this in other post, and K. Barthelmuss said I was
mis-interpreting it's proper use.

So, any enlightenment on:
- Thinking behind typing TTextRec.Userdata as array[1..32] of byte.
- Any code (preferably VCL) that uses this field, especially if used
for other purposes (than pointer). I.E use individual bytes for ???.
- Any dangers in using this field for 'creative' purposes... (i.e.
ursurping a Delphi use of this field).

Thanks:
JMcKay

Peter Below (TeamB)

unread,
Jan 17, 2001, 2:14:16 PM1/17/01
to
In article <3A65D662...@California.com>, Jim McKay wrote:
> I'm confused as to typing of TTextRec.UserData as byte array, and also
> proper use of this record field.

Jim,

this field is called Userdata for a reason: it is there explicitely for your own
use when you write textfile device drivers, the runtime-library makes no use
whatsoever of this field. You can put up to 32 bytes of data of your own choosing
into this area (just see it as a buffer, without any particular data type). There
is no problem to use the first 4 bytes of UserData as storage for some pointer. By
code uses it to store the stream reference (a pointer), for example. Accessing the
data as the correct type is a bit awkward, you either use Move to copy the
appropriate number of bytes to and from a variable of the correct type when you
need it or use creative typecasting.

Jim McKay

unread,
Jan 17, 2001, 2:30:22 PM1/17/01
to

"Peter Below (TeamB)" wrote:
>
> In article <3A65D662...@California.com>, Jim McKay wrote:
> > I'm confused as to typing of TTextRec.UserData as byte array, and also
> > proper use of this record field.
>
> Jim,
>
> this field is called Userdata for a reason:

Makes sense: still, I've gotten in trouble before making assumptions
w/out documentation.

> it is there explicitely for your own use when you write textfile device drivers,

Thanks... that's what I wanted to hear.

> the runtime-library makes no use
> whatsoever of this field. You can put up to 32 bytes of data of your own choosing
> into this area (just see it as a buffer, without any particular data type). There
> is no problem to use the first 4 bytes of UserData as storage for some pointer. By
> code uses it to store the stream reference (a pointer), for example. Accessing the
> data as the correct type is a bit awkward, you either use Move to copy the
> appropriate number of bytes to and from a variable of the correct type when you
> need it or use creative typecasting.

Again, thanks for clarification.

JMcKay

Jason Hochwender

unread,
Jan 19, 2001, 10:39:21 AM1/19/01
to
On Thu, 04 Jan 2001 17:20:29 +0100, "Peter Below (TeamB)"
<10011...@compuXXserve.com> wrote:

>In article <93017b$dt...@bornews.inprise.com>, Mark Genovese wrote:
>> I would like to use a stream to read and write text files, much like the way
>> that ReadLn( ) and WriteLn( ) work. Does anyone know an easy way to do
>> this?
>
>Mark,
>
>there is a little-known but utterly cool feature in Borlands Pascal (since TP
>1.0 i think) that allows one to implement textfile-style IO on about any kind
>of data stream: text-file device drivers. Using the unit below you can attach
>a stream to a Textfile variable and then use Write/WriteLn/Read/ReadLn as
>usual. Has only be superficially tested!

I have just started learning about streams in Delphi and had been
thinking about using a stream to read and write text files as well. I
love learning about all the little known tips in Delphi so I has happy
to see that Peter had posted some code samples related to this. I
have looked at the code but I am having a really hard time
understanding how I would implement it. Peter, do you have any
additional code samples that show how you might go about using your
unit? It doesn't have to be fancy at all. I really think it would
make more sense to me if I could see the unit in use.

Thanks
Jason

Peter Below (TeamB)

unread,
Jan 19, 2001, 2:14:39 PM1/19/01
to
In article <3a685dbd...@newsgroups.borland.com>, Jason Hochwender wrote:
> I have just started learning about streams in Delphi and had been
> thinking about using a stream to read and write text files as well. I
> love learning about all the little known tips in Delphi so I has happy
> to see that Peter had posted some code samples related to this. I
> have looked at the code but I am having a really hard time
> understanding how I would implement it. Peter, do you have any
> additional code samples that show how you might go about using your
> unit? It doesn't have to be fancy at all. I really think it would
> make more sense to me if I could see the unit in use.

There really isn't much too it, you create a stream of some kind, use
AssignStream to attach it to a Textfile variable and then read or write to that
as if it were a normal disk textfile.

Var
ms: TMemoryStream;
f: Textfile;
Begin
ms: TMemorystream.Create;
try
AssignStream( f, ms );
Rewrite(f);
try
WriteLn(f, 'This is some text, followed by a number: ', 16 );
... more output to f
finally
Closefile(f);
end;
ms.position := 0;
memo1.lines.loadfromstream(ms);
finally
ms.free
end;

Jim McKay

unread,
Jan 19, 2001, 3:01:59 PM1/19/01
to

Jason Hochwender wrote:

> I have just started learning about streams in Delphi and had been
> thinking about using a stream to read and write text files as well. I
> love learning about all the little known tips in Delphi so I has happy
> to see that Peter had posted some code samples related to this. I
> have looked at the code but I am having a really hard time
> understanding how I would implement it. Peter, do you have any
> additional code samples that show how you might go about using your
> unit? It doesn't have to be fancy at all. I really think it would
> make more sense to me if I could see the unit in use.

Ray Lischner's book "Secrets of Delphi 2" layed out use of streams
very well. Even though D2, most of it still very relevant.

JMcKay

Jason Hochwender

unread,
Jan 22, 2001, 10:12:03 AM1/22/01
to
Ok, the code that was posted is making sense to me now. It seems
obvious and I am not sure why it didn't make sense to me before.
Anyway, thank you Peter for posting the code and thank you Jim for the
book reference.

Jason

0 new messages