Boost
他のサードパーティ ライブラリを使用せずに、自分でバイナリ シリアル化を実装したいと思います。
C++ でこれを実現する最も簡単な方法はofstream
、バイナリ ファイルを使用してネットワーク経由で送信することです。しかし、ファイルをディスクに書き込むのを避けるために一時バッファとして使用できる他のストリーム クラスはありますか?
また、どうすれば純粋なCでそれを達成できますか?
Boost
他のサードパーティ ライブラリを使用せずに、自分でバイナリ シリアル化を実装したいと思います。
C++ でこれを実現する最も簡単な方法はofstream
、バイナリ ファイルを使用してネットワーク経由で送信することです。しかし、ファイルをディスクに書き込むのを避けるために一時バッファとして使用できる他のストリーム クラスはありますか?
また、どうすれば純粋なCでそれを達成できますか?
持続性は難しい問題です。オブジェクトをディスクにシリアル化することさえ簡単ではありません。たとえば、C で次のような構造があるとします。
struct Person {
char name[100];
int year;
};
これは、sef を含む構造であり、おそらくシリアライゼーションを実際に適用できる最も簡単な方法です。ただし、次の問題に直面する必要があります。
コンパイラのパディング システム。メモリ内の整数の単語を占有するようにメモリ内の構造を完成させる方法は、標準的ではありません。
オペレーティング システムとマシン自体がデータをバイナリ形式で表現する方法。明らかに、この表現はマシンごとに異なります。
結論として、同じオペレーティング システムの同じプログラムで作成されたファイルであっても、同じオペレーティング システムの同じプログラムと互換性がない可能性があります。これは、両方のプログラムが異なる C コンパイラでコンパイルされている可能性があるためです。
C++ でオブジェクトを見てみましょう。
class Person {
public:
// more things...
private:
string name;
Date * birth;
Firm * firm;
};
今、まさに同じことが非常に複雑になっています。オブジェクトはもはや自己完結型ではありません。各オブジェクトをどのように処理するかを決定するために、ポインターに従う必要があります (これは、3. ポインターのスウィズリングおよび推移的な永続性と呼ばれます)。そして、まだ 1) と 2) の問題があります。
自己完結型のオブジェクトに焦点を当て、ポイント 1 と 2 の解決策が必要だとしましょう。唯一の方法は、a) テキスト形式または b) バイトコード形式のいずれかで表現を決定することです。情報はバイトごとに読み書きされるため、バイトコード形式は、任意の C コンパイラでコンパイルされた任意のオペレーティング システムの任意のプログラムで理解できます。これは、Java または C# がオブジェクトをシリアル化する方法です。表現としてのテキスト形式はバイトコードと同じくらい有効ですが、速度は遅くなります。その主な利点は、コンピューターだけでなく人間も理解できることです (構造化されたテキスト形式は XML である可能性があります)。
したがって、自己完結型のオブジェクトをシリアル化するには、選択した出力形式に関係なく、int、char、文字列などを読み取ることができる基本的な関数 (または C++ のクラス) が必要です。それぞれに書き込み/読み取りのペアがある場合、要素データの読み取り/書き込みのペアを使用して、プログラマーがオブジェクトの独自の書き込み/読み取りのペアを作成できるようにする必要があります。
ここでは、Python がpickleモジュールで提供するもののような、完全なフレームワークについて話しています。
最後に、シリアライゼーションをディスクに保存する代わりにキャッシュできるという事実は、問題の中で最も小さいものです。テキストベースのフォーマットを使用している場合はクラスを使用でき、ostringstream
バイトコードを使用している場合はメモリ ブロックを使用できます。
ご覧のとおり、単純な仕事ではありません。お役に立てれば。
データのシリアル化にJSONを使用しています。それはとても良いことです。JSON を正しく取得するのは簡単で、何か問題があるかどうかを簡単に判断できます。
他の形式ほどスペース効率は良くありませんが、多くの目的には十分です。また、JSON Web サイトから入手できる無料のライブラリ コードもあります。
純粋な C では、 Binn形式を使用できます。
サンプルコード:
binn *obj;
// create a new object
obj = binn_object();
// add values to it
binn_object_set_int32(obj, "id", 123);
binn_object_set_str(obj, "name", "John");
binn_object_set_double(obj, "total", 2.55);
// send over the network or save to a file...
send(sock, binn_ptr(obj), binn_size(obj));
// release the buffer
binn_free(obj);
免責事項:私は作成者です
場合によっては、単純型を扱うときに次のことができます。
object o;
socket.write(&o, sizeof(o));