2011-01-12 10 views
5

How to write bitset data to a file?ベクトルにはどのようにベクトル<bool>またはビットセットを格納しますが、ビット単位で格納しますか?

初回の回答では、8倍以上のスペースが必要となるため、質問に正しく答えられません。

どうすればよいですか?真実/偽の値をたくさん保存するには本当に必要です。

+0

実際、私はそれが私の質問の各ビットを1バイトとして保存していることに気にしませんでした...あいまいに言われました。良いフォローアップの質問。 –

答えて

5

最も簡単な方法:連続した8個のブール値を取り、1バイトとして表現し、そのバイトをファイルに書き込みます。それは多くのスペースを節約します。

ファイルの先頭には、ブール値の値をファイルに書き込むことができます。その数値はファイルからバイトを読み込み、ブール値に変換するのに役立ちます!

-1

つのオプション:

は大きなディスクに(可能性が高い、またはペンス)の余分なポンドをお過ごしください。

一度にビットセットから8ビットを抽出し、それらをバイトに構成して出力ストリームに書き込むルーチンを作成します。

+0

よく私は可能な限り多くを保存したいので、8ファクターで容量を増やして購入バイ購入よりも優れています。 – jokoon

+1

あまり役に立ちません... –

1

一つの方法は、次のようになります。それは何のために何の調整を行うものではありませんので、これは、あなたがビットレイアウトがメモリにされて終わるものを気にしないと仮定していること

std::vector<bool> data = /* obtain bits somehow */ 

// Reserve an appropriate number of byte-sized buckets. 
std::vector<char> bytes((int)std::ceil((float)data.size()/CHAR_BITS)); 

for(int byteIndex = 0; byteIndex < bytes.size(); ++byteIndex) { 
    for(int bitIndex = 0; bitIndex < CHAR_BITS; ++bitIndex) { 
     int bit = data[byteIndex * CHAR_BITS + bitIndex]; 

     bytes[byteIndex] |= bit << bitIndex; 
    } 
} 

注意。しかし、実際に格納されたビット数をシリアル化する限り(ビット数がCHAR_BITSの倍数でない場合をカバーするため)、元々このビットセットやベクトルを同じように逆シリアル化することができます。

(私はそのバケットサイズの計算には満足していませんが、それは午前1時であり、よりエレガントなものを考えるのが難しいです)。

1

ビットセットを圧縮せずに最小限のバイト数を使用する2つの関数を使用したtryがあります。文字の配列でも仕事ができる、しかし、あなたはどのような表現を知らないので、それは多分accrossシステムポータブルではないとして、おそらくビットセットで使用されるメモリの一部のreinterpret_castはを使用して

template<int I> 
void bitset_dump(const std::bitset<I> &in, std::ostream &out) 
{ 
    // export a bitset consisting of I bits to an output stream. 
    // Eight bits are stored to a single stream byte. 
    unsigned int i = 0; // the current bit index 
    unsigned char c = 0; // the current byte 
    short bits = 0;  // to process next byte 
    while(i < in.size()) 
    { 
     c = c << 1;  // 
     if(in.at(i)) ++c; // adding 1 if bit is true 
     ++bits; 
     if(bits == 8) 
     { 
      out.put((char)c); 
      c = 0; 
      bits = 0; 
     } 
     ++i; 
    } 
    // dump remaining 
    if(bits != 0) { 
     // pad the byte so that first bits are in the most significant positions. 
     while(bits != 8) 
     { 
      c = c << 1; 
      ++bits; 
     } 
     out.put((char)c); 
    } 
    return; 
} 

template<int I> 
void bitset_restore(std::istream &in, std::bitset<I> &out) 
{ 
    // read bytes from the input stream to a bitset of size I. 
    /* for debug */ //for(int n = 0; n < I; ++n) out.at(n) = false; 
    unsigned int i = 0;   // current bit index 
    unsigned char mask = 0x80; // current byte mask 
    unsigned char c = 0;   // current byte in stream 
    while(in.good() && (i < I)) 
    { 
     if((i%8) == 0)   // retrieve next character 
     { c = in.get(); 
      mask = 0x80; 
     } 
     else mask = mask >> 1; // shift mask 
     out.at(i) = (c & mask); 
     ++i; 
    } 
} 

注意bitset is(endianness?)

2

バイナリに変換するのに最適なビットセットクラスを使用し、ビットセットがunsigned long以上のサイズの場合は、使用する最適なオプションはboost::dynamic_bitsetです。 (スペースを節約することを心配しているのであれば、それは32以上、さらに64ビットでもあると推測します)。

dynamic_bitsetから、to_block_rangeを使用してビットを基礎となる整数型に書き込むことができます。 from_block_rangeまたはBlockInputIteratorのコンストラクタを使用するか、またはappend()を呼び出して、ブロックからdynamic_bitsetを構築することができます。

これで、元の形式(ブロック)のバイトが得られましたが、まだストリームに書き込んだり読み戻したりするという問題があります。

最初に「ヘッダー」情報を少し保存する必要があります:ブロック数と潜在的にエンディアン。または、標準のエンディアンに変換するマクロを使用することもできます(例:ntohlですが、最も一般的なプラットフォームではないマクロを理想的に使用します。リトルエンディアンの場合は、その方法を保存し、ビッグエンディアンシステム)。

(注:boost :: dynamic_bitsetは、基本的なエンディアンに関係なく、整数型を標準的に変換すると仮定しています。

ストリームに数値バイナリを書き込むには、os.write(&data[0], sizeof(Block) * nBlocks)を使用してください。 read(&data[0], sizeof(Block) * nBlocks)ここで、データはvector<Block>とし、読み取る前にdata.resize(nBlocks)reserve()でない)を実行する必要があります。 (あなたはistream_iteratorまたはistreambuf_iteratorで変わったことをすることもできますが、おそらくresize()が良いでしょう)。

+1

ベクトルでコードを実行しました>後でテストします – jokoon

0
#include "stdio" 
#include "bitset" 
... 
FILE* pFile; 
pFile = fopen("output.dat", "wb"); 
... 
const unsigned int size = 1024; 
bitset<size> bitbuffer; 
... 
fwrite (&bitbuffer, 1, size/8, pFile); 
fclose(pFile); 
関連する問題