ストリームを使ってデータの読み書きを行う
ストリームの使用 への移動
ストリーム クラスはみな、データを読み書きするためのメソッドを共有しています。 これらのメソッドは、次の点で区別されています:
- 読み書きしたバイト数を返すかどうか
- バイト数を知る必要があるかどうか
- エラー時に例外を発生させるかどうか
読み書きのためのストリーム メソッド
Read メソッドは、現在の Position から始まる指定されたバイト数を、ストリームからバッファに読み込みます。 Read は、その後、実際に転送されたバイト数分だけ、位置を進めます。 Read のプロトタイプは次のとおりです:
virtual int __fastcall Read(void *Buffer, int Count);
function Read(var Buffer; Count: Longint): Longint;
Read は、ファイル内のバイト数が分からない場合に便利です。 Read は、実際に転送されたバイト数を返しますが、これは、現在位置以降のデータが Count バイトに満たない場合、Count より少ない場合もあります。
Write メソッドは、バッファからストリームへ、Position から始まる Count 分のバイトを書き込みます。 Write のプロトタイプは次のとおりです:
virtual int __fastcall Write(const void *Buffer, int Count);
function Write(const Buffer; Count: Longint): Longint;
ファイルへの書き込み後、Write は、現在位置を書き込んだバイト数分進め、実際書き込んだバイト数を返しますが、この値は、途中でバッファの終わりに到達した場合や、ストリームが先に一杯になりそれ以上バイトを受け入れられなくなった場合などには、Count よりも少なくなる場合があります。
これらと似たプロシージャに ReadBuffer や WriteBuffer がありますが、Read や Write と異なり、読み書きしたバイト数を返しません。 これらのプロシージャは、例えば構造体を読み込む場合など、バイト数がすでに分かっており、予め必要な場合に便利です。 ReadBuffer および WriteBuffer は、バイトの数が実際のものと一致しない場合、例外を発生させます(EReadError および EWriteError)。 この点が、Read/Write メソッドと異なります(これらは、要求された値と異なるバイト数を返すことができる)。 ReadBuffer および WriteBuffer のプロトタイプは次のとおりです:
virtual int __fastcall ReadBuffer(void *Buffer, int Count);
virtual int __fastcall WriteBuffer(const void *Buffer, int Count);
procedure ReadBuffer(var Buffer; Count: Longint);
procedure WriteBuffer(const Buffer; Count: Longint);
これらのメソッドは、Read および Write メソッドを呼び出し、実際の読み書きを実行します。
コンポーネントの読み書き
TStream には、コンポーネントを読み書きするための特殊なメソッド、ReadComponent および WriteComponent が定義されています。 実行時にコンポーネントを作成または変更する際に、コンポーネントやそのプロパティを保存する一手段として、アプリケーションでこれらのメソッドを使用することができます。
ReadComponent および WriteComponent は、IDE がコンポーネントを、フォーム ファイルに読み書きする際に使用するメソッドです。 フォーム ファイルとの間でコンポーネントをストリーミングする際、ストリーム クラスは、TFiler クラス、TReader、TWriter とやり取りし、フォーム ファイルからオブジェクトを読み込んだり、それらをディスクに書き込みます。
コンポーネント ストリーミング システムの使用に関する詳細については、System.Classes.TStream、System.Classes.TFiler、System.Classes.TReader、System.Classes.TWriter、and System.Classes.TComponent のクラスを参照してください。
文字列の読み書き
読み書き関数へ文字列を渡す際、正しい構文を知る必要があります。 読み書きルーチンの Buffer パラメータは、それぞれ var および const 型です。 これらは型のないパラメータなので、ルーチンは、変数のアドレスを取ります。
文字列を操作するデフォルトの型は UnicodeString です。 ただし、長い文字列を Buffer パラメータとして渡すと、正しい結果が生成されません。 長い文字列には、サイズ、参照カウント、文字列内の文字へのポインタが格納されています。 結果として、長い文字列の逆参照は、ポインタ要素への結果になりません。 まずは文字列を Pointer または PChar にキャストしてから、逆参照する必要があります。 例:
Delphi:
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;