Кодирование файла Хаффмана с помощью bool и std::bitset

Мне нужно закодировать байты файла с помощью метода Хаффмана и записать закодированные биты в другой «сжатый» файл. Что я должен использовать для хранения закодированных битов, 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. Спасибо. Извиняюсь за длинный вопрос.


person WDRKKS    schedule 16.03.2015    source источник
comment
Похоже, кто-то получил эту домашнюю работу до того, как вы прочитали и написали побитовое кодирование в c для кодирования по Хаффману. [1]: stackoverflow.com/questions/26442093/   -  person AnthonyLambert    schedule 16.03.2015
comment
@AnthonyLambert Этого не было, когда я искал сайт. И я всегда ищу, прежде чем опубликовать, потому что кто хочет, чтобы его отругали за создание дубликата? Однако это не дубликат. У ОП проблема с распаковкой. У меня нет такой проблемы. Моя проблема заключается в неправильной записи закодированных битов в файл. А также я спросил о предпочтениях bool и bitset.   -  person WDRKKS    schedule 16.03.2015
comment
просто пометил это, потому что они решали одну и ту же проблему на одном языке ... Я же не отругал тебя, не так ли ?! +1 за поддержку и поднятие настроения!   -  person AnthonyLambert    schedule 16.03.2015
comment
@AnthonyLambert Нет, я не имел в виду, что вы отчитываете меня. Я просто защищался от людей, которые обычно хватались за эту возможность, если думали, что ОП не знает о проблеме. Но ты в порядке. И спасибо за поддержку. :-) Вы знаете, как я могу решить эту проблему?   -  person WDRKKS    schedule 16.03.2015
comment
ну, лично я бы использовал беззнаковый символ (байт) и сдвинул в него биты. байт = (байт ‹‹ 1) | (кусочек); и записывать его в файл каждые 8 ​​смен.   -  person AnthonyLambert    schedule 16.03.2015
comment
@AnthonyLambert Хорошо... Спасибо, что сказали мне это. Но у меня есть пара вопросов. Нужно ли мне изменить метод Write_Encoded_File()? Это правильно? А также, на что ссылается bit в вашем решении? Как это связано с std::vector<bool>? Пожалуйста, скажите мне это, спасибо.   -  person WDRKKS    schedule 17.03.2015