RAD Studio |  |

Using Streams to Read or Write Data
Stream methods for reading and writing | Reading and writing components | Reading and writing strings | See Also
Collapse All

Stream classes all share several methods for reading and writing data. These methods are distinguished by whether they:

- Return the number of bytes read or written.
- Require the number of bytes to be known.
- Raise an exception on error.

Stream methods for reading and writing

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:

Copy Code

    function Read(var Buffer; Count: Longint): Longint;

Copy Code

    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:

Copy Code

    function Write(const Buffer; Count: Longint): Longint;

Copy Code

    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:

Copy Code

    procedure ReadBuffer(var Buffer; Count: Longint);
    procedure WriteBuffer(const Buffer; Count: Longint);

Copy Code

    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.

Reading and writing components

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.

Reading and writing strings

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:

Copy Code

    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;

See Also

Copying Data from One Stream to Another

Specifying the Stream Position and Size

Copyright(C) 2009 Embarcadero Technologies, Inc. All Rights Reserved.
What do you think about this topic? Send feedback!