前のページ次のページ上に戻るホーム SophiaFramework UNIVERSE 5.3

17.3. バイナリストリーム

バイナリストリームは、バイナリ列(任意の型のデータ)を読み書きするためのストリームです。 下記の表にあるように、読み書きのタイプに応じて 2 種類のバイナリストリームが存在します。

表 17.5. バイナリストリーム

データの型 読み込み用 書き込み用
任意の型 SFXBinaryStreamReader SFXBinaryStreamWriter

17.3.1. バイナリストリームを利用したバイナリ列の読み書き

17.3.1.1. バイナリストリームからのバイナリ列読み込み

例 17.10. 読み込むバイナリ列: "/dir/data.txt"

12 34 56 78 11 22 33 44 55  // HEX 形式(16 進数表示)

例 17.11. バイナリストリームからのバイナリ列読み込み

// *** 以下のコードでは、エラー処理が省略されています。 
SFXFile file;                  // ファイル
SFXBinaryStreamReader reader;  // ファイル読み込み用バイナリストリーム

// 読み込みモードでファイルを開く
file.OpenReadOnly(SFXPath("/dir/data.txt"));

// ファイル読み込み用バイナリストリームを取得する
// ※ size 引数を指定していないのでストリームバッファは可変長
file.GetStreamReader(&reader);

// ファイルからストリームバッファにデータを読み込む
// ※1. 読み込んだデータのサイズに合わせてストリームバッファは自動的に拡張される
// ※2. 可変長バッファストリームの場合、1 回の Fetch 関数呼び出しで読み込みは完了する
reader.Fetch();

// バイナリ列をリトルエンディアンとして解釈する
reader >> little;

UInt32 v;

// ストリームバッファから各変数にデータを読み込む
reader >> v; // 先頭から 4 バイトを UInt32 として解釈する
             // リトルエンディアンなので、v に 0x78563412 が代入される

// 以降のバイナリ列をビッグエンディアンとして解釈する
reader >> big;

reader.ReadUInt32(&v); // 次の 4 バイトを UInt32 として解釈する
                       // ビッグエンディアンなので v = 0x11223344
                       // reader >> v と同じ

UInt08 c;

reader >> c; // 先頭から 1 バイトを UInt08 として解釈する : c = 0x55

reader.ReadUInt08(&c); // 先頭から 1 バイトを取得しようとするが、末尾まできたので c は変化しない
                       // この関数はエラーを返す

// ファイル読み込み用バイナリストリームを解放する
reader.Release();

// ファイルを閉じる
file.Close();
[Note] エクストラクタ(>> 演算子)と Read 系関数の違い

エクストラクタ(>> 演算子)はエラー値を返しませんが、 Read 系関数はエラー値を返します。

17.3.1.2. バイナリストリームへのバイナリ列書き込み

例 17.12. バイナリストリームへのバイナリ列書き込み

// *** 以下のコードでは、エラー処理が省略されています。 
SFXFile file;                  // ファイル
SFXBinaryStreamWriter writer;  // ファイル書き込み用バイナリストリーム

// 読み書きモードでファイルを開く
file.OpenReadWrite(SFXPath("/dir/data.txt"));

// ファイル書き込み用バイナリストリームを取得する
// ※ size 引数を指定していないのでストリームバッファは可変長
file.GetStreamWriter(&writer);

// バイナリ列をリトルエンディアンとして解釈する
writer << little;

// ストリームバッファに各種データを書き込む
// ※ 書き込んだデータのサイズに合わせてストリームバッファは自動的に拡張される
writer.WriteUInt08(0x22);  // UInt08 として書き込む
writer.WriteUInt16(0x22);  // UInt16 として書き込む
writer.WriteUInt32(0x22);  // UInt32 として書き込む

// writer << 0x22; は曖昧なのでエラー
// writer << static_cast<UInt08>(0x22); なら可

// 以降のバイナリ列をビッグエンディアンとして解釈する
writer << big;

// ストリームバッファにデータを書き込む
// ※ 書き込んだデータのサイズに合わせてストリームバッファは自動的に拡張される
writer.WriteUInt32(0x22); // UInt32 として書き込む

// ストリームバッファからファイルにデータを書き込む
// ※ 可変長バッファストリームの場合、1 回の Flush 関数呼び出しで書き込みは完了する
writer.Flush();

// ファイル書き込み用バイナリストリームを解放する
writer.Release();

// ファイルを閉じる
file.Close();

例 17.13. 書き込まれたバイナリ列: "/dir/data.txt"

22 22 00 22 00 00 00 00 00 00 22  // HEX 形式(16 進数表示)
[Note] インサータ(<< 演算子)と Write 系関数の違い

インサータ(<< 演算子)はエラー値を返しませんが、 Write 系関数はエラー値を返します。

17.3.2. バイナリストリームを利用した文字列クラスの読み書き

バイナリストリームReadSFXAnsiString/ReadSFXWideString 関数や WriteSFXAnsiString/WriteSFXWideString 関数の引数、または インサータ(<< 演算子)やエクストラクタ(>> 演算子) のオペランドに SFXAnsiString / SFXWideString インスタンスを指定することで文字列クラスのデータをストレージに読み書きできます。

17.3.2.1. バイナリストリームから文字列クラスへの読み込み

バイナリストリームから文字列クラスのデータを読み込む場合、 次の '\0' までのデータを SFXAnsiString / SFXWideString 型変数に読み込みます。

この場合、予めその変数のサイズを指定する必要はありません。 変数のメモリ領域は、 読み込んだ文字列の長さに合わせて自動的に確保されます。

[Note] バッファクラスに読み込む場合

SFXBuffer 型変数にデータを読み込む場合は、 予めその変数のサイズを指定する必要があります。 変数のメモリ領域は自動的に確保されません。

[Caution] 終端までに '\0' が見つからない場合

終端までに '\0' が見つからない場合はエラーとなり、 変数に文字列は格納されません(変数の内容は読み込む前の状態のままです)。 このとき、ReadSFXAnsiString / ReadSFXWideString 関数は SFERR_INVALID_STATE を返しますが、 エクストラクタ(>> 演算子はエラーを返しません。

[Note] 文字列ストリームから文字列を読み込む場合

文字列ストリームから文字列を読み込む場合は、 終端が '\0' でなくともエラーは発生せず、終端までのデータを 1 つの文字列として読み取ります。

[Tip] '\0' セパレータ
ストリーム内で文字列を区切るセパレータである '\0' は、 AChar 型文字列(SFXAnsiString)の場合は 1 バイト、 WChar 型文字列(SFXWideString)の場合は 2 バイトです。

例 17.14. 読み込む文字列: "/dir/data.txt"

61 62 63 64 00 65 66 67 68 00 69 6A 6B 6C  // HEX 形式(16 進数表示)

例 17.15. バイナリストリームから文字列クラスへの読み込み

// *** 以下のコードでは、エラー処理が省略されています。 
SFXFile file;                  // ファイル
SFXBinaryStreamReader reader;  // ファイル読み込み用バイナリストリーム
SFXAnsiString string;          // 読み込む文字列

// 読み込みモードでファイルを開く
file.OpenReadOnly(SFXPath("/dir/data.txt"));

// ファイル読み込み用バイナリストリームを取得する
// ※ size 引数を指定していないのでストリームバッファは可変長
file.GetStreamReader(&reader);

// ファイルからストリームバッファにデータを読み込む
// ※1. 読み込んだデータのサイズに合わせてストリームバッファは自動的に拡張される
// ※2. 可変長バッファストリームの場合、1 回の Fetch 関数呼び出しで読み込みは完了する
reader.Fetch();

// ストリームバッファから string 変数にデータを読み込む
reader >> string; // '\0' までのデータを文字列として取得する  string = "abcd"
reader >> string; // 次の '\0' までを取得する                 string = "efgh"

// この時点で、残りの末尾までに '\0' がない
reader >> string;   // このとき、ストリームから読み込もうとしても string = "efgh" のままで変化しない
                    // Read 関数で読み込む場合は SFERR_INVALID_STATE が返る

// ファイル読み込み用バイナリストリームを解放する
reader.Release();

// ファイルを閉じる
file.Close();

17.3.2.2. バイナリストリームへの文字列クラスの書き込み

バイナリストリームWriteSFXAnsiString / WriteSFXWideString 関数や、 インサータ(<< 演算子)を利用して、 SFXAnsiString / SFXWideString 文字列をストリームに書き込むと、文字列の末尾に '\0' が自動的に挿入されます。

[Caution] 文字列ストリームの場合

文字列ストリームに書き込む場合は、 文字列の末尾に '\0' は挿入されません。

[Tip] '\0' セパレータ
ストリーム内で文字列を区切るセパレータである '\0' は、 AChar 型文字列(SFXAnsiString)の場合は 1 バイト、 WChar 型文字列(SFXWideString)の場合は 2 バイトです。

例 17.16. バイナリストリームへの文字列クラスの書き込み

// *** 以下のコードでは、エラー処理が省略されています。 
SFXFile file;                  // ファイル
SFXBinaryStreamWriter writer;  // ファイル書き込み用バイナリストリーム
SFXAnsiString string("abcd");  // 書き込む文字列

// 読み書きモードでファイルを開く
file.OpenReadWrite(SFXPath("/dir/data.txt"));

// ファイル書き込み用バイナリストリームを取得する
// ※ size 引数を指定していないのでストリームバッファは可変長
file.GetStreamWriter(&writer);

// string 変数からストリームバッファにデータを書き込む
// ※ 書き込んだデータのサイズに合わせてストリームバッファは自動的に拡張される
writer << string; // 文字列 "abcd" と '\0' が書き込まれる
writer << string; // 文字列 "abcd" と '\0' が書き込まれる

// ストリームバッファからファイルにデータを書き込む
// ※ 可変長バッファストリームの場合、1 回の Flush 関数呼び出しで書き込みは完了する
writer.Flush();

// ファイル書き込み用バイナリストリームを解放する
writer.Release();

// ファイルを閉じる
file.Close();

例 17.17. 書き込まれた文字列: "/dir/data.txt"

61 62 63 64 00 61 62 63 64 00  // HEX 形式(16 進数表示)

17.3.3. バイナリストリームを利用したバッファクラスの読み書き

Read 関数や Write 関数の引数、または インサータ(<< 演算子) やエクストラクタ(>> 演算子) のオペランドに SFXBuffer インスタンスを指定することでバッファクラスのデータをストレージに読み書きできます。

[Caution] 注意
バイナリストリームでは、 インサータ(<< 演算子) やエクストラクタ(>> 演算子) の右オペランドに SFXBuffer インスタンスを指定できます。 しかし、文字列ストリームでは指定できません。

17.3.3.1. バイナリストリームからバッファクラスへの読み込み

バイナリストリームから SFXBuffer 型変数にデータを読み込む場合は、 予めその変数のサイズを指定する必要があります。 変数のメモリ領域は自動的に確保されません。

[Note] 文字列クラスに読み込む場合

SFXAnsiString / SFXWideString 型変数に読み込む場合は、 予めその変数のサイズを指定する必要はありません。

変数のメモリ領域は、 読み込んだ文字列の長さに合わせて自動的に確保されます。

[Caution] 注意
設定したサイズより少ないデータしか読み込めない場合は、 エラーになります。

例 17.18. 読み込むバイナリ列: "/dir/data.txt"

11 22 33 44 55 11 22 33 44 55 22  // HEX 形式(16 進数表示)

例 17.19. バイナリストリームからバッファクラスへの読み込み

// *** 以下のコードでは、エラー処理が省略されています。 ***
SFXFile file;                  // ファイル
SFXBinaryStreamReader reader;  // ファイル読み込み用バイナリストリーム
SFXBuffer buffer;  // 読み込むバッファ
buffer.SetSize(4); // あらかじめ読み込むサイズを設定しておく必要がある

// 読み込みモードでファイルを開く
file.OpenReadOnly(SFXPath("/dir/data.txt"));

// ファイル読み込み用バイナリストリームを取得する
// ※ size 引数を指定していないのでストリームバッファは可変長
file.GetStreamReader(&reader);

// ファイルからストリームバッファにデータを読み込む
// ※1. 読み込んだデータのサイズに合わせてストリームバッファは自動的に拡張される
// ※2. 可変長バッファストリームの場合、1 回の Fetch 関数呼び出しで読み込みは完了する
reader.Fetch();

// ストリームバッファから buffer 変数にデータを読み込む
reader >> buffer;   // 最初の 4 バイトを取得する  buffer には 11 22 33 44 (HEX 形式) が格納される
reader >> buffer;   // 次の 4 バイトを取得する    buffer には 55 11 22 33 (HEX 形式) が格納される

// この時点でストリームバッファに残っているデータは 3 バイト
// buffer のサイズは 4 バイトなので読み込もうとするデータの方がストリームバッファに残っているデータよりも大きい
reader >> buffer;  // このとき、ストリームから読み込もうとしても buffer の内容は 55 11 22 33 (HEX 形式) のままで変化しない
                   // Read 関数で読み込む場合は SFERR_FAILED エラーが返る

// ファイル読み込み用バイナリストリームを解放する
reader.Release();

// ファイルを閉じる
file.Close();

17.3.3.2. バイナリストリームへのバッファクラスの書き込み

例 17.20. バイナリストリームへのバッファクラスの書き込み

// *** 以下のコードでは、エラー処理が省略されています。 
SFXFile file;                  // ファイル
SFXBinaryStreamWriter writer;  // ファイル書き込み用バイナリストリーム
SFXBuffer buffer;              // バッファ
AChar data[] = {0x11, 0x22, 0x33, 0x44, 0x55};  // バッファに設定するデータ

buffer.Set(data, 5);  // buffer に 5 バイトのデータを設定する

// 読み書きモードでファイルを開く
file.OpenReadWrite(SFXPath("/dir/data.txt"));

// ファイル書き込み用文字列ストリームを取得する
// ※ size 引数を指定していないのでストリームバッファは可変長
file.GetStreamWriter(&writer);

writer << buffer; // buffer 変数からストリームバッファにデータ(5 バイト)を書き込む
writer << buffer; // buffer 変数からストリームバッファにデータ(5 バイト)を書き込む

// ストリームバッファからファイルにデータを書き込む
// ※ 可変長バッファストリームの場合、1 回の Flush 関数呼び出しで書き込みは完了する
writer.Flush();

// ファイル書き込み用バイナリストリームを解放する
writer.Release();

// ファイルを閉じる
file.Close();

例 17.21. 書き込まれたバイナリ列: "/dir/data.txt"

11 22 33 44 55 11 22 33 44 55  // HEX 形式(16 進数表示)

17.3.4. 簡易パーサーとしてのバイナリストリーム

バイナリストリームは簡易パーサーとして利用できます。

例えば、

// *** 以下のコードでは、エラー処理が省略されています。 
SFXBinaryStreamWriter writer;  // 出力バイナリストリーム
SFXBinaryStreamReader reader;  // 入力バイナリストリーム
SFXAnsiString data1("ansi string1");
SFXAnsiString data2("ansi string2");
SFXWideString data3("wide string");
SInt32 data4 = -10;
UInt16 data5 = 20;
Bool data6 = true;

SFXBuffer buffer;

AChar temp[] = {0x11, 0x22, 0x33, 0x44, 0x55};

buffer.Set(temp, 5);

で、

// 読み書きモードでファイルを開く
file.OpenReadWrite(SFXPath("/dir/data.txt"));

// ファイル書き込み用ストリームを取得する
// ※ size 引数を指定していないのでストリームバッファは可変長
file.GetStreamWriter(&writer);

// ストリームバッファに各種変数のデータを書き込む
// ※ 書き込んだデータのサイズに合わせてストリームバッファは自動的に拡張される
writer << data1 << data2 << data3 << data4 << data5 << data6 << buffer;

// ストリームバッファからファイルにデータを書き込む
// ※ 可変長バッファストリームの場合、1 回の Flush 関数呼び出しで書き込みは完了する
writer.Flush();

// ファイル書き込み用ストリームを解放する
writer.Release();

// ファイルを閉じる
file.Close();

として書き込んだデータは、

buffer.SetSize(5);

// 読み込みモードでファイルを開く
file.OpenReadOnly(SFXPath("/dir/data.txt"));

// ファイル読み込み用ストリームを取得する
// ※ size 引数を指定していないのでストリームバッファは可変長
file.GetStreamReader(&reader);

// ファイルからストリームバッファにデータを読み込む
// ※1. 読み込んだデータのサイズに合わせてストリームバッファは自動的に拡張される
// ※2. 可変長バッファストリームの場合、1 回の Fetch 関数呼び出しで読み込みは完了する
reader.Fetch();

// ストリームバッファから各種変数にデータを読み込む
reader >> data1 >> data2 >> data3 >> data4 >> data5 >> data6 >> buffer;

// ファイル読み込み用ストリームを解放する
reader.Release();

// ファイルを閉じる
file.Close();

として読み込めます。

[Caution] 制約条件

簡易パーサーは、書き込むときのデータと読み込むときのデータに関して、 順序と型が一致しなければ正しく動作しません。 また、複数の '\0' を含む文字列についても正しく動作しません。