考虑字符串"010010101
"。我想把上面的字符串以二进制格式存储在一个文件中。我想这样做是因为当我执行以下代码时:
ofstream out("file.txt");
out << string;
文件大小太大。我想通过在文件中以二进制格式存储0和1来减小文件大小。
您可以将字节写入文件
例如
#include <fstream>
...
char buffer[100];
ofstream myFile ("data.bin", ios::out | ios::binary);
myFile.write (buffer, 100);
现在我们知道如何写入字节,我们只需要知道如何将字符串转换为要写入的字节值。
假设您的字符串不是用unicode编码的,我们可以简单地使用ascii表来发现"1"表示数值49,"0"表示数值48。
有了这些知识,您可以在字符串的每8个字符中迭代,每个"1"或"0"的子字符串48将为您提供数值。然后将8个数字一起移位,直到得到字节。如果少于8个字符,则需要放置前导零。
我懒得写代码,但我想有了这些知识,你应该能够写一个很好的工作算法。
只需使用此函数将'0'
和'1'
字符的字符串转换为压缩二进制字符串:
string pack_bin (string const & s)
{
string ret;
ret.reserve ((s.size() + 7) / 8);
for (unsigned i = 0; i < s.size(); )
{
char c = 0;
for (unsigned j = 0; j < 8; ++j, ++i)
c = (c << 1) | ((s[i] != '0') ? 1 : 0);
ret += c;
}
return ret;
}
反过来:
string unpack_bin (string const & s)
{
string ret;
ret.reserve (s.size() * 8);
for (unsigned i = 0; i < s.size(); ++i)
for (int j = 7; j >= 0; --j)
ret += ((s[i] & (1 << j)) ? '1' : '0');
return ret;
}
注意以下内容:
- 如果字符串的长度不是8的倍数,则必须将长度与生成的字符串一起存储,以便能够恢复您所拥有的确切字符串。否则,解压缩后的字符串末尾将有额外的零
- 最好将结果字符串写入二进制文件,即
ofstream out("file.txt", ios:binary);
你可以像这样使用上面的例程:
// To write:
ofstream out ("file.txt", ios::binary);
out << pack_bin(str);
// To read back:
ifstream in ("file.txt", ios::binary);
string s;
in >> s;
s = unpack_bin (s);