![]() ![]() ![]()
|
BREW C++ ライブラリ & GUI フレームワーク & XML ミドルウェア : SophiaFramework 4.1 |
ストリームは、以下の 6 種類があります。
表 17.1. ストリーム
| データの種類 | 入力ストリーム | 出力ストリーム |
|---|---|---|
| 文字列 ストリーム ( AChar 型文字列用 ) | SFXAnsiStringStreamReader | SFXAnsiStringStreamWriter |
| 文字列 ストリーム ( WChar 型文字列用 ) | SFXWideStringStreamReader | SFXWideStringStreamWriter |
| バイナリ ストリーム( バイナリ列用 ) | SFXBinaryStreamReader | SFXBinaryStreamWriter |
![]() |
AChar と WChar について |
|---|---|
|
BREW には、シングルバイト文字またはマルチバイト文字を表す char 型と、 BREW 独自の 2 バイト文字を表す AECHAR 型があります。 SophiaFramewok では、これら 2 種類の文字型をそれぞれ AChar 型、WChar 型として定義しています。 文字列を表すクラスには、AChar 型の文字で構成される SFXAnsiString と、 WChar 型の文字で構成される SFXWideString の 2 種類があります。 | |
文字列ストリームは、文字列を読み書きするためのストリームです。
例 17.2. 文字列の読み込み
SFXAnsiStringStreamReader reader; SFXAnsiString string; reader >> string; // '\0' までのデータを文字列として取得する string = "abcd" reader >> string; // 次の '\0' までを取得する string = "efgh" reader >> string; // 末尾までを取得する string = "ijkl" reader >> string; // 末尾までを取得する string = 空
'\0' が見つからない場合は、終端までを文字列とします。
例 17.3. 文字列の書き込み
SFXAnsiStringStreamWriter writer;
SFXAnsiString string("abcd");
writer << string; // "abcd" を書き込む
writer << "efgh"; // "efgh" を書き込む
writer << string; // "abcd" を書き込む
結果は "abcdefghabcd" となります。結果の文字列に '\0' は挿入されません。
バイナリ ストリームは、バイナリ列を読み書きするストリームです。
例 17.6. バイナリ列の読み込み
SFXBinaryStreamReader reader; // 入力バイナリ ストリーム // reader の取得部分は省略 // バイナリ列をリトル エンディアンとして解釈する 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 は変化しない // この関数はエラーを返す
![]() |
注意 |
|---|---|
| Read?????? 関数はエラー値を返す点がインサータ ( >> ) と異なります。 | |
例 17.7. バイナリ列の書き込み
SFXBinaryStreamWriter writer; // 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 として書き込む writer.Flush();
SFXBuffer クラスや SFXAnsiString ( SFXWideString ) クラスのインスタンス変数もストリームの引数またはオペランドに指定できます。
例 17.10. バッファからの読み込み
SFXBuffer buffer; buffer.SetSize(4); // あらかじめ読み込むサイズを設定しておく必要がある reader >> buffer; // 最初の 4 バイトを取得する buffer には 11 22 33 44 ( 16 進数 ) が格納される reader >> buffer; // 次の 4 バイトを取得する buffer には 55 11 22 33 ( 16 進数 ) が格納される reader >> buffer; // エラー 残りの 2 バイトが読み込まれる訳ではない
buffer にはサイズを指定する必要があります。自動的にバッファが拡張されることはありません。
また、設定したサイズより少ないデータしか残っていない場合は、エラーになります。
例 17.14. 文字列から読み込み
SFXAnsiString string; reader >> string; // '\0' までのデータを文字列として取得する string = "abcd" reader >> string; // 次の '\0' までを取得する string = "efgh" reader >> string; // 末尾に '\0' がないのでエラー string = 変化なし
文字列の読み込みは '\0' をセパレータ ( 区切り ) として、セパレータまでのデータを SFXAnsiString と解釈して読み込みます。'\0' が見つからない場合はエラーとなり、文字列は格納されません。
バイナリ ストリームは簡易パーサーとして利用できます。
例えば、
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);
で、
writer << data1 << data2 << data3 << data4 << data5 << data6 << buffer;
として書き込んだデータは、
buffer.SetSize(5); reader >> data1 >> data2 >> data3 >> data4 >> data5 >> data6 >> buffer;
として読み込めます。
![]() |
注意 |
|---|---|
| 読み込む順番や型を変えると正しく動作しません。 | |
入出力ストリームのバッファは、ストレージから読み込んだデータ分だけ自動的に拡張されます。
メモリを節約するには、ストリーム バッファのサイズを固定にして、複数回に分けてデータを読み込みます。
例 17.17. 固定長バッファによるファイル入力
SFCError error; // エラー値 SFXFile file; // ファイル クラス のインスタンス SFXAnsiStringStreamReader reader; // ファイル読み込み用ストリーム SFXAnsiString stringFromFile; // この変数にデータが読み込まれる SFXAnsiString tempString; // 読み込みモードでファイルをオープンする if ((error = file.OpenReadOnly(SFXPath("/dir1/data.txt"))) == SFERR_NO_ERROR) { // ファイル読み込み用ストリームを取得する ( 1024 はバッファ サイズ ) if ((error = file.GetStreamReader(1024, &reader)) == SFERR_NO_ERROR) { while (!reader.Ends()) { // ファイル読み込み用ストリームの終端に到達するまで繰り返す // データを読み込む // バッファサイズを指定しているので、1024 バイトしか読み込まれない if ((error = reader.Fetch()) != SFERR_NO_ERROR) { // エラーのとき break; } // tempString にデータを読み込む if ((error = reader.ReadSFXAnsiString(&tempString)) != SFERR_NO_ERROR) { // エラーのとき break; } // stringFromFile の末尾に tempString を加える stringFromFile += tempString; } reader.Release(); } file.Close(); }
上のコードでは、バッファ サイズを 1024 バイトに設定しているので、 1 回の Fetch 関数の呼び出しで 1024 バイトまでのデータしか読み込まれません。 Fetch 関数の呼び出しを何回か繰り返してデータを読み込む必要があります。
例 17.18. 固定長バッファによるファイル出力
SFCError error; // エラー値 SFXFile file; // ファイル SFXAnsiStringStreamWriter writer; // ファイル書き込み用ストリーム SFXAnsiString string("abcdefghijklmnopqrstuvwxyz"); // 書き込むデータ ACharConstPtr p = string.GetBuffer(); // 文字列を指すポインター ACharConstPtr endOfString = p + string.GetLength(); // 文字列の末尾 SInt32 bufferSize = 1024; // 読み書きモードでファイルをオープンする if ((error = file.OpenReadWrite(SFXPath("/dir1/data.txt"))) == SFERR_NO_ERROR) { // ファイル書き込み用ストリームを取得する if ((error = file.GetStreamWriter(bufferSize, &writer)) == SFERR_NO_ERROR) { for (; p < endOfString; p += bufferSize) { // 書き込むサイズ SInt32 size = (endOfString - p < bufferSize) ? endOfString - p : bufferSize; // 文字列を書き込む if ((error = writer.Write(p, size)) != SFERR_NO_ERROR) { break; // エラー } // 実際にファイルにデータを書き込む if ((error = writer.Flush()) != SFERR_NO_ERROR) { // エラーのとき break; } } writer.Release(); } file.Close(); }
例 17.19. 固定長バッファによる TCP ソケット通信
class MyClass {
private:
SFXTCPSocket _socket; // TCP ソケットクラス
SFXAnsiStringStreamReader _reader; // データ受信用ストリーム
SFXAnsiStringStreamWriter _writer; // データ送信用ストリーム
SFXAnsiString _writingString; // 送信する文字列
ACharConstPtr _p;
ACharConstPtr _end;
SInt32 _bufferSize;
SFXAnsiString _readingString; // 受信する文字列
public:
Void Start(Void);
CALLBACK_DECLARE_SFXTCPSOCKET(OnConnect)
CALLBACK_DECLARE_SFXANSISTRINGSTREAMREADER(OnFetch)
CALLBACK_DECLARE_SFXANSISTRINGSTREAMWRITER(OnFlush)
};
Void MyClass::Start(Void)
{
// 送信する文字列
_writingString = "GET / HTTP/1.1\r\n\r\n";
_bufferSize = 1024;
// 初期処理
_socket.Open();
// 接続開始 ( 接続の完了は、OnConnect 関数に通知される )
_socket.Connect(SFXSocketAddress("www.example.com:80"), CALLBACK_FUNCTION(OnConnect));
}
// 接続の完了が通知されるコールバック関数
CALLBACK_IMPLEMENT_SFXTCPSOCKET(MyClass, OnConnect, error)
{
// データ受信用ストリームを取得する
_socket.GetStreamReader(1024, &_reader);
// データ送信用ストリームを取得する
_socket.GetStreamWriter(_bufferSize, &_writer);
_p = _writingString.GetBuffer();
_end = _p + _writingString.GetLength();
SInt32 size = (_end - _p < _bufferSize) ? _end - _p : _bufferSize;
// データ送信用ストリームにデータを書き込む
_writer.Write(_p, size);
_p += size;
// 実際にデータを送信する ( データ送信の完了は、OnFlush 関数に通知される )
_writer.Flush(CALLBACK_FUNCTION(OnFlush));
}
// データ送信の完了が通知されるコールバック関数
CALLBACK_IMPLEMENT_SFXANSISTRINGSTREAMWRITER(MyClass, OnFlush, error)
{
if (_p < _end) { // 送信するものが残っているとき
// 再度、データ送信用ストリームにデータを書き込む
SInt32 size = (_end - _p < _bufferSize) ? _end - _p : _bufferSize;
// データ送信用ストリームにデータを書き込む
_writer.Write(_p, size);
_p += size;
// 実際にデータを送信する ( データ送信の完了は、OnFlush 関数に通知される )
_writer.Flush(CALLBACK_FUNCTION(OnFlush));
}
else { // データの受信
// データを受信する ( データ受信の完了は、OnFetch 関数に通知される )
_reader.Fetch(CALLBACK_FUNCTION(OnFetch));
// ここで _reader.Read 関数を呼び出すとエラーになる
}
}
// データ受信の完了が通知されるコールバック関数
CALLBACK_IMPLEMENT_SFXANSISTRINGSTREAMREADER(MyClass, OnFetch, error)
{
SFXAnsiString temp;
// 受信したデータを temp 変数に格納する
_reader.ReadSFXAnsiString(&temp);
_readingString += temp;
if (!_reader.Ends()) { // データ受信用ストリームの終端でないとき
// データを受信する ( データ受信の完了は、OnFetch 関数に通知される)
_reader.Fetch(CALLBACK_FUNCTION(OnFetch));
}
}
サイズの大きなデータは、何回か繰り返し Fetch 関数を呼び出して読み込み(受信)ます。 そのたびにコールバック関数(OnFetch 関数)が呼び出されます。
また、サイズの大きなデータも、何回か繰り返し Flush 関数を呼び出して書き込み(送信)ます。 そのたびにコールバック関数(OnFlush 関数)が呼び出されます。
Fetch / Flush 関数で登録したコールバック関数が呼び出されるタイミングは、データの終端まで読み込んだときか、ストリーム バッファにデータが無くなったときです。
SetTrigger 関数を使うとそれ以外のタイミング(トリガー)を設定できます。
例 17.20. TCP ソケット通信で、改行文字 "\r\n" が現れるたびにコールバック関数が呼び出されるようにトリガーを設定する
// 一部抜粋、エラー処理は省略 // 接続の完了が通知されるコールバック関数 CALLBACK_IMPLEMENT_SFXTCPSOCKET(MyClass, OnConnect, error) { // データ受信用ストリームを取得する _socket.GetStreamReader(&_reader); // "\r\n"を読み込んだタイミングでコールバック関数が呼び出されるようにトリガーを設定する _reader.SetTrigger("\r\n", 2); // データを受信する ( データ受信の完了は、OnFetch 関数に通知される ) _reader.Fetch(CALLBACK_FUNCTION(OnFetch)); } // データ受信の完了が通知されるコールバック関数 CALLBACK_IMPLEMENT_SFXANSISTRINGSTREAMREADER(MyClass, OnFetch, error) { SFXAnsiString string; // SetTrigger で指定したトリガーがこのコールバック関数に通知されたかどうか // (この場合のトリガー: 改行文字が現れたとき) if (_reader.Triggers()) { TRACE("by CRLF"); } // 受信した文字列を string 変数に読み込む _reader.ReadSFXAnsiString(&string); while (!_reader.Ends()) { // データ受信用ストリームの終端でないかぎり // データ受信をする ( データ受信の完了は、OnFetch 関数に通知される ) _reader.Fetch(CALLBACK_FUNCTION(OnFetch)); } }
![]() |
注意 |
|---|---|
| 指定した文字数を読み込む、或いは書き込む度にコールバック関数を呼び出すような設定も可能です。 | |
|
Copyright (C) 2002 - 2008 Sophia Cradle, Inc. All Rights Reserved. |
![]() ![]() ![]()
|