我需要通过Huffman方法对文件的字节进行编码,并将编码的位写入另一个&#34;压缩&#34;文件。我应该使用什么来存储编码位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()
函数读取Binary中的文件并将其存储在std::vector<std::uint8_t>
中。然后,Generate_Byte_Frequency()
创建字节及其频率的std::map
。我不是在这里发布代码,因为它完美无缺。我将其打印出来进行检查,它也可用于小文件和大文件(long
用于大文件,但int
现在可以使用。 Binary_Tree类构造函数Huffman_Tree()
也很完美。它使用std::priority_queue
构建一个Huffman_Tree,并将它们放入std::map<std::uint8_t, std::vector<bool>>
,其中存储每个字节及其相应的编码值。
问题可能出在Encode()
方法或Write_Encoded_File()
方法中。在对文件进行编码并将编码值写入另一个文件后,我得到了一个94KB输出文件,用于94KB输入文件。我不认为问题出在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, ""));
}
最后,main函数中的Decode()
和Write_Decoded_File()
方法完美地为我提供了完全相同的输入文件。此外,由于Encode()
方法的返回值是作为Decode()
方法的参数给出的,这进一步证明Encode()
方法正常工作。在这种情况下,这意味着我错误地将它写入编码文件。请帮我纠正一下。另外,请告诉我有关bool vs. bitset
偏好的信息。谢谢。对长期问题道歉。