MemoryStreamがマネージドメモリへの読み書きを行うのに対して、UnmanagedMemoryStreamクラスはポインタで表されるアンマネージメモリに対する読み書きを行うためのStreamです。 ポインタからUnmanagedMemoryStreamクラスのインスタンスを作成する以外の操作方法はStreamクラスと同じです。
Streamクラスを使ってポインタに対する読み書きが行えるようになるため、アンマネージメモリに対してBinaryReader・BinaryWriterを使った読み書きができるようになります。
UnmanagedMemoryStreamクラス
UnmanagedMemoryStreamクラスのインスタンスを作成するには、コンストラクタでアンマネージメモリブロックの先頭を表すbyte*
型のポインタと、メモリブロックの長さを指定します。
メモリブロックへの書き込みを行いたい場合は、FileAccess.Write
またはFileAccess.ReadWrite
を指定します。
IntPtrを使ってUnmanagedMemoryStreamインスタンスを作成することはできないため、VB.NETなどポインタ型を持たない言語では、他の言語で作成されたラッパーを使用するなどするか、Marshalクラスを使用して読み書きを行う必要があります。
UnmanagedMemoryStreamは常に既存のアンマネージメモリブロックを操作します。 MemoryStreamとは異なり、UnmanagedMemoryStream自体はバッファを確保する機能を持ちません。 また、UnmanagedMemoryStreamはコンストラクタで指定したアンマネージメモリブロックの解放も行いません。 メモリブロックの確保・解放などの管理は使用者側で行う必要があります。
UnmanagedMemoryStreamでは、コンストラクタでアクセス可能なメモリブロックの長さを指定することができます。 あらかじめ指定された範囲を超えてアクセスしようとした場合にはNotSupportedExceptionがスローされます。 また、指定されたFileAccessで許可されていないアクセス(読み込み・書き込み)を行おうとした場合にもNotSupportedExceptionがスローされます。
インスタンスを作成して以降の操作は、通常のStreamと同様に操作を行うことができます。 また、UnmanagedMemoryStreamとBinaryReader・BinaryWriterと組み合わせて使用することもできます。
以下の例は、構造体のポインタからUnmanagedMemoryStreamを作成し、BinaryWriterに使って書き込みを行う例です。
この例で使用しているStructLayout属性についてはフィールドのレイアウト・オフセットを参照してください。
UnmanagedMemoryStreamクラスの使用例
バイト配列に変換
以下はUnmanagedMemoryStreamクラスを使って、メモリブロックの内容をバイト配列に変換する例です。 なお、メモリブロックから配列へのコピーにはMarshal.Copyメソッドを用いることもできます。
memcpy/CopyMemory
以下はUnmanagedMemoryStreamクラスでmemcpy
/CopyMemory
相当の処理を行う例です。 コピー元・コピー先ブロックのポインタそれぞれからUnmanagedMemoryStreamインスタンスを作成し、CopyToメソッドでコピーを行います。
このほかにmemcpy
/CopyMemory
相当の処理を行う手法やそのパフォーマンスについてはバイト列操作 §.メモリブロックのコピー手法とパフォーマンスで解説・検証しています。
この例で用いているCopyToメソッドは.NET Framework 4以降で使用可能なメソッドであるため、.NET Framework 3.5以前の場合はReadメソッド・Writeメソッドを使ってコピー処理を記述する必要があります。 コピー処理の実装例はストリームの基本とStreamクラス §.コピー (CopyTo))で紹介しています。