所以,我正在编写 LZ77 压缩算法。以下是程序要求:
- 程序应压缩任何未压缩的文件(.txt、.bmp 等)
- 基于上述,程序应该使用二进制
现在事情开始对我来说有点不清楚,所以我需要一些建议。以下是我对这个问题的看法:
输入文件应以std::ios::binary
. 下一个是什么?为方便起见,我认为将二进制作为字节使用是最佳的,对于我正在使用的字节解释chars
(因为 1 char 等于 1 字节,如果我没记错的话)。因此我将文件数据作为字节(chars
)读取到细绳。string
现在我可以使用算法对这个字节进行编码。编码的输出是三元组向量. 现在我需要将此输出数据解释为字节以保存到压缩文件中,对吗?因为offset和length是ints
,所以我需要将它们分成字节(chars)以将它们写入输出二进制流(因为ofstream::write
争论是 char* 和要插入的字符数(字节))。nextchar
可以按原样写。对于解码,我将步骤颠倒过来:从文件中读取三元组字节,然后使用算法进行解码。
我错过了一些重要的东西吗?在这种情况下使用字节是否正确?有什么错误的逻辑吗?下面是一些代码:
// Construct int from bytes
int intFromBytes(std::istream& is)
{
char bytes[4];
for (int i = 0; i < 4; ++i)
is.get(bytes[i]);
int integer;
std::memcpy(&integer, &bytes, 4);
return integer;
}
// Get bytes from int
void intToBytes(std::ostream& os, int value)
{
char bytes[4];
std::memcpy(&bytes, &value, 4);
os.write(bytes, 4);
}
struct Node
{
int offset, length;
char next;
}
///// Packing /////
// Open and read binary data as a byte string
void readFileUnpacked(std::string& path)
{
std::ifstream file(path, std::ios::in | std::ios::binary);
if (file.is_open())
{
Buffer = std::string(std::istreambuf_iterator<char>(file), {});
file.close();
}
}
///// Here should be the encoding logic /////
// Writing encoded triplets as bytes
void createFilePacked(std::string& path)
{
std::ofstream out(path, std::ios::out | std::ios::binary);
if (out.is_open())
{
for (auto node : encoded)
{
intToBytes(out, node.offset);
out << node.next;
intToBytes(out, node.length);
}
out.close();
}
}
///// Unacking /////
// Reading packed file as binary
readFilePacked(std::string& path)
{
std::ifstream file(path, std::ios::in | std::ios::binary);
if (file.is_open())
{
Node element;
while (file.peek() != std::ifstream::traits_type::eof())
{
element.offset = intFromBytes(file);
file.get(element.next);
element.length = intFromBytes(file);
encoded.push_back(element);
}
file.close();
}
}
///// Here should be the decoding logic /////
createFileUnpacked(std::string& newpath)
{
std::ofstream out(newpath, std::ios::out | std::ios::binary);
out << Buffer;
out.close();
}