Мне нужно закодировать байты файла с помощью метода Хаффмана и записать закодированные биты в другой «сжатый» файл. Что я должен использовать для хранения закодированных битов, std::vector<bool>
или std::vector<std::bitset<1>>
? Мне предложили использовать std::bitset<8>
сами по себе, но, поскольку они являются битами, закодированными Хаффманом, их длина зависит от частоты байтов. И std::bitset
должен иметь постоянную длину, что означает, что более длинные закодированные значения потеряют свои самые значащие биты, а более короткие закодированные значения будут дополнены дополнительными нулями, тем самым изменяя значения. Есть ли способ преодолеть это? Мне сказали, что std::vector<bool>
не очень предпочтителен, потому что это не массив C-стиля. Могу ли я вместо этого использовать std::vector<std::bitset<1>>
? Есть ли в нем недостатки? Скажите мне, пожалуйста.
ПРИМЕЧАНИЕ. Это школьное задание, поэтому я не должен использовать ничего, кроме C++ и STL. Поэтому, пожалуйста, не предлагайте библиотеки Boost или что-то подобное, потому что я не могу их использовать.
Еще одно очень важное замечание: я пытался использовать std::vector<bool>
, но не получил желаемого результата.
int main()
{
std::string Input_File_Name, Encoded_Output_File_Name, Decoded_Output_File_Name;
Input_File_Name = "C:\\Users\\WDR\\Pictures\\grrm.jpg";
Encoded_Output_File_Name = Input_File_Name + ".encoded";
Decoded_Output_File_Name = Input_File_Name + ".decoded";
File_Handler File;
std::vector<std::uint8_t> File_Data = File.Read_Input_File(Input_File_Name);
std::map<std::uint8_t, int> File_Byte_Frequency = File.Generate_Byte_Frequency(Input_File_Name);
Binary_Tree Huffman_Tree(File_Byte_Frequency.begin(), File_Byte_Frequency.end());
std::vector<bool> Encoded_Bytes = Huffman_Tree.Encode(File_Data.begin(), File_Data.end());
File.Write_Encoded_File(Encoded_Bytes, Encoded_Output_File_Name);
std::vector<std::uint8_t> Decoded_File_Data;
Huffman_Tree.Decode(Encoded_Bytes, std::back_inserter(Decoded_File_Data));
File.Write_Decoded_File(Decoded_File_Data, Decoded_Output_File_Name);
return 0;
}
Функция Read_Input_File()
читает файл в двоичном формате и сохраняет его в формате std::vector<std::uint8_t>
. Затем Generate_Byte_Frequency()
создает std::map
байта и его частоты. Я не публикую этот код здесь, потому что он отлично работает. Я распечатал его для проверки, и он работает и с маленькими, и с большими файлами (long
для больших файлов, но int
пока работает). Конструктор класса Binary_Tree Huffman_Tree()
также отлично работает. Он строит Huffman_Tree, используя std::priority_queue
, и помещает их в std::map<std::uint8_t, std::vector<bool>>
, где хранится каждый байт и соответствующее ему закодированное значение.
Проблема может быть в методе Encode()
или методе Write_Encoded_File()
. После кодирования файла и записи закодированных значений в другой файл я получаю выходной файл размером 751 КБ для входного файла размером 94 КБ. Я не думаю, что проблема в методе Encode()
, потому что он работает для кодирования строк символов. Таким образом, это должен быть метод письма. Тем не менее, я публикую оба метода здесь.
std::vector<bool> Binary_Tree::Encode(std::vector<std::uint8_t>::iterator First_Element, std::vector<std::uint8_t>::iterator Last_Element)
{
std::vector<bool> Byte_Encoding;
while(First_Element != Last_Element)
{
std::map<std::uint8_t, std::vector<bool>>::iterator Current_Element = Encoded_Values.find(*First_Element);
Byte_Encoding.insert(Byte_Encoding.end(), Current_Element->second.begin(), Current_Element->second.end());
++First_Element;
}
return Byte_Encoding;
}
void File_Handler::Write_Encoded_File(std::vector<bool> &Encoded_Data, const std::string &Output_File_Name)
{
std::ofstream Output_File(Output_File_Name, std::ios::binary);
if(!Output_File)
{
throw std::runtime_error("Unable to write to file: " + Output_File_Name);
}
std::copy(Encoded_Data.begin(), Encoded_Data.end(), std::ostream_iterator<bool>(Output_File, ""));
}
Наконец, методы Decode()
и Write_Decoded_File()
в основной функции работают отлично, давая мне точно такой же входной файл. Более того, поскольку возвращаемое значение метода Encode()
передается в качестве аргумента методу Decode()
, это еще одно свидетельство того, что метод Encode()
работает правильно. В этом случае это означает, что я неправильно записываю его в закодированный файл. Пожалуйста, помогите мне исправить это. Также, пожалуйста, расскажите мне о предпочтениях bool vs. bitset
. Спасибо. Извиняюсь за длинный вопрос.
Write_Encoded_File()
? Это правильно? А также, на что ссылаетсяbit
в вашем решении? Как это связано сstd::vector<bool>
? Пожалуйста, скажите мне это, спасибо. - person WDRKKS   schedule 17.03.2015