【发布时间】:2019-11-30 16:13:59
【问题描述】:
我正在编写 LZ77 压缩算法,但无法将无符号字符存储在字符串中。为了压缩任何文件,我使用它的二进制表示,然后将其读取为chars(因为 1 char 等于 1 字节,afaik)到std::string。 chars 一切正常。但经过一段时间的谷歌搜索后,我了解到char 并不总是 1 个字节,因此我决定将其换成unsigned char。事情开始变得棘手:
- 压缩纯 .txt 时,一切都按预期工作,我在解压缩前后得到相同的文件(我认为应该如此,因为我们基本上在字节转换前后处理文本)
- 但是,当尝试压缩 .bmp 时,与输入文件相比,解压缩文件会丢失 3 个字节(尝试将无符号字符保存到 std::string 时会丢失这 3 个字节)
所以,我的问题是 – 有没有办法将无符号字符正确保存到 一个字符串?
我尝试使用 typedef basic_string<unsigned char> ustring 并将所有相关函数换成它们的基本替代品以与 unsigned char 一起使用,但我仍然丢失了 3 个字节。
更新:我发现 3 个字节(符号)丢失不是因为 std::string,但因为
std::istream_iterator(我使用std::istreambuf_iterator) 创建无符号字符串 (因为std::istreambuf_iterator的参数是字符,不是无符号的 字符)
那么,有什么办法可以解决这个特定的问题吗?
例子:
std::vector<char> tempbuf(std::istreambuf_iterator<char>(file), {}); // reads 112782 symbols
std::vector<char> tempbuf(std::istream_iterator<char>(file), {}); // reads 112779 symbols
示例代码:
void LZ77::readFileUnpacked(std::string& path)
{
std::ifstream file(path, std::ios::in | std::ios::binary);
if (file.is_open())
{
// Works just fine with char, but loses 3 bytes with unsigned
std::string tempstring = std::string(std::istreambuf_iterator<char>(file), {});
file.close();
}
else
throw std::ios_base::failure("Failed to open the file");
}
【问题讨论】:
-
char何时不是 1 个字节? -
为什么不是 std::vector?
-
我认为您正在寻找的是 std::vector
。我不确定标准是否保证了对 uint8_t 的支持,但如果是,它将恰好有 8 位。 -
您不想使用
std::string- 在许多地方都假定字符串是空终止的,这不是您想要的。使用std::vector。无需担心char不是 8 位。这样的系统很少见,而且除了您的小型存档代码之外,肯定不会有其他东西可以在上面工作。 -
@asymmetriq "我读到在某些平台上 char 不能等于 1 字节(因为标准显然没有定义它的确切大小)" - 标准明确假设
char的大小为一个字节(sizeof(char)始终返回 1)。它没有说的是一个字节有多大。是的,有些平台(尽管现在很少见)一个字节的大小不是 8 位。请参阅CHAR_BIT了解给定平台上的实际大小