Не очень полезно на всех ...

аписать данные набора битов в файл?

Первый ответ не дает правильного ответа на вопрос, поскольку он занимает в 8 раз больше места, чем следовало бы.

Как бы вы это сделали? Мне действительно нужно, чтобы сохранить много истинных / ложных значений.

 Tony R07 янв. 2012 г., 23:32
На самом деле мне было все равно, что в моем вопросе он хранит каждый бит как байт ... это было сформулировано двусмысленно. Хороший дополнительный вопрос.

Ответы на вопрос(6)

Решение Вопроса

взять 8 последовательных логических значений, представить их как один байт, записать этот байт в ваш файл. Это сэкономит много места.

В начале файла вы можете написать номерлогический значения, которые вы хотите записать в файл; это число поможет при чтении байтов из файла и преобразовании их обратно в логические значения!

Одним из способов может быть:

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), вы можете десериализовать точно такой же набор битов или вектор, как вы изначально любили это ,

(Я не в восторге от этого расчета размера корзины, но сейчас час ночи, и мне трудно придумать что-то более элегантное).

которые будут использовать минимальное количество байтов без сжатия набора битов.

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

Обратите внимание, что, вероятно, использование reinterpret_cast части памяти, используемой набором битов в качестве массива символов, также может сработать, но, возможно, это не переносимо во всех системах, потому что вы не знаете, что такое представление набора битов (endianness?)

который лучше всего поддерживает преобразование в двоичный файл, и ваш набор битов больше размера unsigned long, то лучшим вариантом для использования являетсяповышение :: dynamic_bitset, (Я предполагаю, что это больше 32 и даже 64 бит, если вы заинтересованы в экономии места).

Из dynamic_bitset вы можете использовать to_block_range для записи битов в базовый целочисленный тип. Вы можете создать dynamic_bitset обратно из блоков с помощью from_block_range или его конструктора из BlockInputIterator или с помощью вызовов append ().

Теперь у вас есть байты в их собственном формате (блок), у вас все еще есть проблема записи его в поток и чтения его обратно.

Сначала вам нужно будет сохранить немного информации «заголовка»: количество блоков и, возможно, порядковый номер. Или вы можете использовать макрос для преобразования в стандартный порядок байтов (например, 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 (), вероятно, лучше).

 jokoon12 янв. 2011 г., 16:24
Я сделал некоторый код с вектором <bitset <64 >>, я проверю это позже

Потратьте лишние килограммы (или пенсов, скорее всего) на больший диск.

Напишите процедуру для извлечения 8 битов из набора битов за раз, скомпонуйте их в байты и запишите их в выходной поток.

 jokoon12 янв. 2011 г., 11:00
ну, я хочу хранить как можно больше, поэтому увеличение емкости в 8 раз лучше, чем покупка покупка покупка.
 Tony R07 янв. 2012 г., 23:31
Не очень полезно на всех ...
#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);

Ваш ответ на вопрос