iostream で元の型のままデータを保存する

[戻る]
紅' 2009/11/17(火) 17:25:24
紅'と申します。
お知恵をお貸しください。

VC2003 MFC でプログラムを作成します。
以下のようなことをしたいと思っています。

・いろいろな型のデータの集合がある
・上記のデータにインデクスなどを付加した上で、
 ひとかたまりのデータとしてメモリに保管する

要するに、

 void* a[] = { new int( 5 ), "123", new char( 10 ), ... };

この様なデータにインデクス(例えば int なら 1、文字列なら 2 という感じです)を
くっつけて、以下のような形に変換したいと考えています。

 0x01,0x05,0x02,0x31,0x32,0x33,0x00,0x02,0x0a ...

ここで元のデータ数が不定のため、iostream と streambuf の継承クラスを使って
処理済のデータを次々にバッファに追加していく方法を思いつきました。
ただ、試したところ、iostream に << 0x01 などの形で整数値を追加しても
内部で文字列に変換されてしまうようです。( sprintf を使っていました)

これを数値のまま streambuf の継承クラスに渡す方法はないでしょうか。

ご教示をいただけたら幸いです。
よろしくお願いします。

以上です。

isshi 2009/11/17(火) 23:19:44
>・いろいろな型のデータの集合がある
>・上記のデータにインデクスなどを付加した上で、
> ひとかたまりのデータとしてメモリに保管する

iostream にこだわっているのでなければ、boost::any が使えると思います。

std::vector<boost::any> v;
v.push_back(5);
v.push_back(std::string("123"));
v.push_back('\x0a');

επιστημη [E-Mail] [HomePage] 2009/11/18(水) 08:42:57
↑回答/解決案になってないんじゃないかと。

επιστημη [E-Mail] [HomePage] 2009/11/18(水) 08:48:13
↓ずいぶん昔に書いたものです。参考になれば。
http://www.s34.co.jp/cpptechdoc/article/serialize/index.html

tetrapod 2009/11/18(水) 09:37:19
ofstream os("abc.txt");
os<<0x01; は当然ながら 1 という文字 (ASCII なら 0x31) が出力される。
ソース上の 0x01 という記法が int だから。
文字コード 0x01 を出力したかったら os << '\x01' となるわけだ。

で、えぴ氏の記事は Endian/sizeof 依存なので
「読み書きソースコード互換」ではあっても
「データファイル互換」ではない
ため、異種マシンでデータファイル互換が必要だとさらに一工夫必要。

えぴ氏の記事とは反対側のアプローチ例を挙げておこう。
void* に異種オブジェクトを入れてしまうと元の型が不明になってしまうので
class serializable { ... }; という「シリアライズ可能抽象型」をつくり、
実際に扱うデータは
class data_a : public serializable { ... };
class data_b : public serializable { ... };
のように「シリアライズ可能な型」としておく、とか。

紅' 2009/11/18(水) 10:54:11
[[解決]]
ご返信をありがとうございます。

isshi さん
やりたいことはそのものなのですが、boost は断られてしまいました。

実は、std::stream 系はほとんど使ったことがなかったのでこれを機に
手を出してみようかなと思ったのがきっかけで。
シリアライズをちゃんと出来れば特にこだわりがあったわけでも
ありませんでした。

機会があればそのときにチャレンジしてみたいと思います。
ありがとうございました。


επιστημηさん
記事、参考になります。
‥‥ write メソッドを使えばよかったんですね。自分、なんで気づかないかな。
「シリアライズ」という言葉を忘れていました。余計に恥ずかしい。。。
おそらく、<< 演算子のオーバーロードをすることで対応とすることになると
思います。ありがとうございました。


tetrapod さん
os << '\x01' って方法もあったのですね。こちらは本当に知りませんでした。
ダメじゃん自分。。。

エンディアンはデータを作成するときに hton とかを入れればよいかなと
思っていました。が、sizeof は不安になったので念押ししておくことにします。
「シリアライズ可能抽象型」についても、今回どこまで汎用性を考えるべきか
不明な点もあるのですが、設計に取り入れてみたいと思います。
ご忠告をありがとうございました。


以上で、解決とさせていただきます。

επιστημη [E-Mail] [HomePage] 2009/11/18(水) 11:10:27
> やりたいことはそのものなのですが

うそーん。型情報消えてねぇ?

isshi 2009/11/18(水) 11:52:42
>うそーん。型情報消えてねぇ?
boost::any::type() で typeid が分かりますが、それではダメなのでしょうか?
boost::any_cast でキャストに失敗すれば bad_any_cast が throw されるので、
型情報は消えてないと思うのですが。

紅' 2009/11/18(水) 16:08:22
こんにちわ。
返信をありがとうございます。

たしかに厳密に言えば少し違うかもしれません。
環境がなくていまは確かめられないので申し訳ないのですが、
適用しようとしたケースに当てはめるには少し工夫が必要になるようです。

ただし、isshi さんのおっしゃられている方法で型も(たぶん)取れますし、
なによりそのお手軽さに魅了されました。深い。。。


昨日からいじっていてやっとアンマネージの環境を思い出してきました。
半年程度でここまで忘れてしまうとは驚きです。

古いスレッドには追加発言できません。