Stream classes all share several methods for reading and writing data. These methods are distinguished by whether they:
The Read method reads a specified number of bytes from the stream, starting at its current Position, into a buffer. Read then advances the current position by the number of bytes actually transferred. The prototype for Read is:
function Read(var Buffer; Count: Longint): Longint;
virtual int __fastcall Read(void *Buffer, int Count);
Read is useful when the number of bytes in the file is not known. Read returns the number of bytes actually transferred, which may be less than Count if the stream did not contain Count bytes of data past the current position.
The Write method writes Count bytes from a buffer to the stream, starting at the current Position. The prototype for Write is:
function Write(const Buffer; Count: Longint): Longint;
virtual int __fastcall Write(const void *Buffer, int Count);
After writing to the file, Write advances the current position by the number bytes written, and returns the number of bytes actually written, which may be less than Count if the end of the buffer is encountered or the stream can't accept any more bytes.
The counterpart procedures are ReadBuffer and WriteBuffer which, unlike Read and Write, do not return the number of bytes read or written. These procedures are useful in cases where the number of bytes is known and required, for example when reading in structures. ReadBuffer and WriteBuffer raise an exception (EReadError and EWriteError) if the byte count can not be matched exactly. This is in contrast to the Read and Write methods, which can return a byte count that differs from the requested value. The prototypes for ReadBuffer and WriteBuffer are:
procedure ReadBuffer(var Buffer; Count: Longint); procedure WriteBuffer(const Buffer; Count: Longint);
virtual int __fastcall ReadBuffer(void *Buffer, int Count); virtual int __fastcall WriteBuffer(const void *Buffer, int Count);
These methods call the Read and Write methods to perform the actual reading and writing.
TStream defines specialized methods, ReadComponent and WriteComponent, for reading and writing components. You can use them in your applications as a way to save components and their properties when you create or alter them at runtime.
ReadComponent and WriteComponent are the methods that the IDE uses to read components from or write them to form files. When streaming components to or from a form file, stream classes work with the TFiler classes, TReader and TWriter, to read objects from the form file or write them out to disk. For more information about using the component streaming system, see TStream, TFiler, TReader, TWriter, and TComponent classes.
If you are passing a string to a read or write function, you need to be aware of the correct syntax. The Buffer parameters for the read and write routines are var and const types, respectively. These are untyped parameters, so the routine takes the address of a variable.
The most commonly used type when working with strings is a long string. However, passing a long string as the Buffer parameter does not produce the correct result. Long strings contain a size, a reference count, and a pointer to the characters in the string. Consequently, dereferencing a long string does not result in the pointer element. You need to first cast the string to a Pointer or PChar, and then dereference it. For example:
procedure caststring; var fs: TFileStream; const s: string = 'Hello'; begin fs := TFileStream.Create('temp.txt', fmCreate or fmOpenWrite); fs.Write(s, Length(s));// this will give you garbage fs.Write(PChar(s)^, Length(s));// this is the correct way end;
Copyright(C) 2009 Embarcadero Technologies, Inc. All Rights Reserved.
What do you think about this topic? Send feedback!