Преобразование boost:: dynamic_bitset в строку дает 8-кратное увеличение размера

Я пытаюсь превратить boost::dynamic_bitset в string, чтобы передать его функции сжатия. Я могу преобразовать его с помощью boost::to_string, но это приводит к увеличению количества битов в 8 раз. Когда я конвертирую обратно из string в boost::dynamic_bitset, это не уменьшает в 8 раз количество используемых битов, что решило бы мою проблему, поскольку это привело бы к тому, что общий объем используемого пространства в конечном итоге был бы исходным количеством сжатых битов.

Я хочу либо остановить 8-кратное увеличение при переходе от boost::dynamic_bitset -> string, либо уменьшить используемое пространство в 8 раз при переходе от boost::dynamic_bitset -> string.

Данные, хранящиеся в boost::dynamic_bitset, поступают из двоичного файла. Вот тот, который я использую, но теоретически любой файл с двоичными данными должен работать.

При выводе количества бит я вызываю string.size(), который возвращает размер в байтах, поэтому я умножаю на 8. boost::dynamic_bitset.size() возвращает размер в битах, поэтому мой вывод должен сравнивать яблоки с яблоками, предполагая, что все правильно .

Вот результат, который я сейчас получаю:

Dynamic bitset input bits = 6431936
String from dynamic_bitset bits = 51455488
Dynamic bitset from string bits = 51455488

Вот мой код:

#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <boost/dynamic_bitset.hpp>
#include <boost/math/cstdfloat/cstdfloat_types.hpp>
#include <boost/numeric/conversion/cast.hpp>

typedef boost::float32_t float32;
typedef boost::uint32_t uint32;

int main() {
   std::vector<unsigned char> data;
   unsigned char *cp;
   float32 value = 8.0;
   boost::uint32_t internal;
   std::memcpy( &internal , &value , sizeof( value ) );

   std::ifstream fin("ex.bin", std::ios::binary);

   while (fin.read(reinterpret_cast<char*>(&internal), sizeof(uint32))) {
      std::memcpy( &value, &internal , sizeof( internal ) );
      cp = (unsigned char *)&internal;

      for(int i = 0; i < 4; ++i) {
         data.push_back(*cp);
         ++cp;
      }
   }

   boost::dynamic_bitset<unsigned char> bitset;
   std::string buffer;

   bitset.init_from_block_range(data.begin(), data.end());

   std::cout << "Dynamic bitset input bits = " << bitset.size() << "\n";

   boost::to_string(bitset, buffer);

   std::cout << "String from dynamic_bitset bits = " << buffer.size()*8 << "\n";

   boost::dynamic_bitset<unsigned char> from_str(buffer.begin(), buffer.end());

   std::cout << "Dynamic bitset from string bits = " << from_str.size() << "\n";

   return 0;
}

person Tommy McDonald    schedule 07.12.2018    source источник
comment
Возможно, вы сравниваете количество байтов с количеством битов?   -  person geza    schedule 07.12.2018
comment
Извлеките минимально воспроизводимый пример. Непонятно, откуда берутся эти цифры, не говоря уже о том, какова их единица.   -  person Ulrich Eckhardt    schedule 07.12.2018
comment
откуда номер который вы цитируете?   -  person 463035818_is_not_a_number    schedule 07.12.2018
comment
Похоже, вы нарушаете требования конструктора набора битов: boost.org/doc/libs/1_63_0/libs/dynamic_bitset/. std::string использует char, но ваш набор битов использует unsigned char   -  person NathanOliver    schedule 07.12.2018
comment
Обновлен пример с лучшим содержанием, надеюсь   -  person Tommy McDonald    schedule 07.12.2018
comment
Имеет ли отношение использование Snappy к вашей проблеме или это просто создание набора битов? Пожалуйста, предоставьте MCVE, который должен содержать простой main(), обязательные включения и ничего лишнего. Кстати: как новый пользователь, также пройдите тур и прочитайте Как спросить.   -  person Ulrich Eckhardt    schedule 07.12.2018
comment
Я обновил проблему с работающей основной и упрощенной проблемой.   -  person Tommy McDonald    schedule 08.12.2018


Ответы (1)


Метод size() в контейнерах C++ идиоматически относится к количеству элементов, а не к количеству байтов.

std::string::size() дает вам количество char значений в строке, а boost::dynamic_bitset::size() возвращает количество хранящихся в ней битов; поскольку вы инициализировали его из n=buffer.size() «блоков» по ​​8 бит каждый (char — это 8 бит практически на любой «нормальной» платформе), вполне ожидаемо, что размер, который он возвращает, в 8 раз больше, в то время как фактическая потребляемая память точно так же.


Редактировать: после последней модификации проблема стала совершенно другой.

boost::to_string не выводит внутреннее компактное представление, а генерирует удобочитаемую строку, состоящую из реальных символов '0' и '1', что приводит к 8-кратному увеличению требуемого размера (выход представляет собой последовательность 8-битных байтов, из которых только один бит эффективно используется).

person Matteo Italia    schedule 07.12.2018
comment
Спасибо, что указали на это. Я считаю, что правильно обновил эту информацию, чтобы отразить это, и у меня похожая, но другая проблема. - person Tommy McDonald; 08.12.2018
comment
@TommyMcDonald, ты полностью изменил текст задачи! Проблема, с которой вы столкнулись сейчас, заключается в том, что to_string не выводит внутреннее компактное представление, а генерирует строку, состоящую из фактических символов '0' и '1', что приводит к 8-кратному увеличению требуемого размера (выход составляет 8 бит байтов, из которых эффективно используется только один бит). - person Matteo Italia; 08.12.2018
comment
Да, я изменил вопрос на тот, где я смог выяснить это на основе ответов. Я попытался создать новый вопрос, но он был помечен как дубликат, поэтому я не знал, что еще делать, кроме как обновить этот, с реальной проблемой все время. - person Tommy McDonald; 08.12.2018
comment
Я смог скопировать dynamic_bitset в строку напрямую, используя boost::to_block_range(input, std::back_inserter(buffer)) но затем функция алгоритма сжатия, которую я пытаюсь использовать, ожидает, что строка не работает. Может быть, выходит за рамки этого вопроса. Пытался включить информацию о библиотеке сжатия, но ему сказали удалить ее. - person Tommy McDonald; 08.12.2018