2011-01-12 7 views

Antwort

5

Einfachster Ansatz: Nehmen Sie nacheinander 8 boolesche Werte, stellen Sie sie als ein einzelnes Byte dar, schreiben Sie dieses Byte in Ihre Datei. Das würde viel Platz sparen.

Am Anfang der Datei können Sie die Nummer schreiben boolean Werte, die Sie in die Datei schreiben möchten; Diese Zahl hilft beim Lesen der Bytes aus der Datei und wandelt sie in boolesche Werte um!

-1

zwei Optionen:

die überflüssigen Pfunde verbringen (oder Pence, was wahrscheinlicher ist) für eine größere Festplatte.

Schreiben Sie eine Routine, um jeweils 8 Bits aus dem Bitset zu extrahieren, sie in Bytes zusammenzufassen und in Ihren Ausgabestrom zu schreiben.

+0

na ich möchte so viel wie möglich speichern, also erhöht sich die kapazität um einen 8 faktor ist besser als kaufen kaufen kaufen. – jokoon

+1

Nicht sehr hilfreich auf alle ... –

1

Eine Möglichkeit könnte sein:

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; 
    } 
} 

Beachten Sie, dass dies voraus, dass Sie sich nicht, was das Bit Layout im Speicher endet als, weil es keine Anpassungen für etwas macht. Aber solange Sie auch die Anzahl der Bits, die tatsächlich gespeichert wurden, serialisieren (um Fälle abzudecken, bei denen Sie eine Bitanzahl haben, die kein Vielfaches von CHAR_BITS ist), können Sie genau dasselbe Bitset oder denselben Vektor deserialisieren wie ursprünglich .

(Ich bin nicht glücklich mit dieser Eimergröße Berechnung, aber es ist 1 Uhr morgens und ich habe Probleme, an etwas eleganteres zu denken).

1

Hier ist ein Versuch mit zwei Funktionen, die eine minimale Anzahl von Bytes verwenden, ohne das Bitset zu komprimieren.

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; 
    } 
} 

Beachten Sie, dass wahrscheinlich ein reinterpret_cast des Teils des Speichers durch die bitset als ein Array von Zeichen könnte auch funktionieren, verwendet verwenden, aber es ist vielleicht nicht tragbar accross Systeme, weil Sie nicht wissen, was die Darstellung der bitset ist (endianness?)

2

Wenn Sie möchten, dass die Bitset-Klasse, die die Konvertierung in Binärwerte am besten unterstützt, und Ihr Bitset mehr als die Länge von unsigned lang hat, ist die beste zu verwendende Option boost::dynamic_bitset. (Ich nehme an, es ist mehr als 32 und sogar 64 Bits, wenn Sie sich Sorgen um Platz sparen).

Von dynamic_bitset können Sie to_block_range verwenden, um die Bits in den zugrunde liegenden Integraltyp zu schreiben. Sie können das dynamic_bitset aus den Blöcken mithilfe von from_block_range oder seinem Konstruktor aus BlockInputIterator oder durch Aufruf von append() aufbauen.

Jetzt haben Sie die Bytes in ihrem nativen Format (Block) Sie haben immer noch das Problem, es in einen Stream zu schreiben und es wieder zu lesen.

Sie müssen zuerst ein bisschen "Header" Informationen speichern: die Anzahl der Blöcke, die Sie haben, und möglicherweise die Endianess.Oder Sie verwenden ein Makro, um in eine Standard-Endiane zu konvertieren (zB ntohl, aber Sie werden idealerweise ein Makro verwenden, das für Ihre gängigste Plattform nicht funktioniert. Wenn Sie also Little Endian verwenden, möchten Sie das wahrscheinlich speichern und nur für konvertieren big-endian Systeme).

(Hinweis: Ich gehe davon aus, dass boost :: dynamic_bitset standardmäßig integrale Typen auf die gleiche Weise konvertiert, unabhängig von der zugrunde liegenden Endianz. Ihre Dokumentation sagt nicht).

Um Zahlen binär in einen Strom zu schreiben, verwenden Sie und zu lesen verwenden. read(&data[0], sizeof(Block) * nBlocks) wo angenommen wird, dass Daten vector<Block> sind und vor dem Lesen müssen Sie data.resize(nBlocks) (nicht reserve()) tun. (Sie können auch komische Sachen mit istream_iterator oder istreambuf_iterator machen, aber resize() ist wahrscheinlich besser).

+1

Ich habe einen Code mit einem Vektor >, ich werde es später testen – 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);