假设我有一个字符数组,char a [8]包含10101010.如果我将此数据存储在.txt文件中,则此文件的大小为8字节。现在我问我怎样才能将这些数据转换为二进制格式并将其保存为8位(而不是8字节)文件,这样文件大小只有1个字节。
另外,一旦我将这8个字节转换为单个字节,我应该将输出保存在哪个文件格式中? .txt或.dat或.bin?
我正在处理文本文件的霍夫曼编码。我已经将文本格式转换为二进制,即0和1,但是当我将此输出数据存储在文件中时,每个数字(1或0)需要一个字节而不是一个字节。我想要一个解决方案,使每个数字只需要一点点。
char buf[100];
void build_code(node n, char *s, int len)
{
static char *out = buf;
if (n->c) {
s[len] = 0;
strcpy(out, s);
code[n->c] = out;
out += len + 1;
return;
}
s[len] = '0'; build_code(n->left, s, len + 1);
s[len] = '1'; build_code(n->right, s, len + 1);
}
这是我在霍夫曼树的帮助下构建代码树的方法。并且
void encode(const char *s, char *out)
{
while (*s)
{
strcpy(out, code[*s]);
out += strlen(code[*s++]);
}
}
这是我编码以获得最终输出的方式。
答案 0 :(得分:1)
不完全确定如何以字符串表示值的二进制表示, 但您可以使用std::strtoul等标准函数从字符串(在任何基础中)中获取整数值。
该函数提供无符号long值,因为您知道您的值在0-255范围内,您可以将其存储在unsigned char中:
unsigned char v =(unsigned char)(std :: strtoul(binary_string_value.c_str(),0,2)& 0xff);
将其写入磁盘,您可以使用ofstream来编写
我应该将输出保存在哪种文件格式中? .txt或.dat或.bin?
请记住,扩展名(。txt,.dat或.bin)并不真正强制格式化(即内容的结构)。扩展名是一个常规常规,用于表示您正在使用某些众所周知的格式(在某些操作系统/环境中,它会驱动哪个程序的配置最佳处理该文件)。由于这是您的文件,因此您需要定义实际格式...并将文件命名为您最喜欢的任何扩展名(甚至没有扩展名)(换句话说,任何最能代表您内容的扩展名)只要它对您和那些将要使用您的文件的人有意义。
假设我们有一个长度的缓冲区,你在那里存储你的字符串'0'和'1'
int codeSize; // size of the code buffer
char *code; // code array/pointer
std::ofstream file; // File stream where we're writing to.
unsigned char *byteArray=new unsigned char[codeSize/8+(codeSize%8+=0)?1:0]
int bytes=0;
for(int i=8;i<codeSize;i+=8) {
std::string binstring(code[i-8],8); // create a temp string from the slice of the code
byteArray[bytes++]=(unsigned char)(std::strtoul(binstring.c_str(),0,2) & 0xff);
}
if(i>codeSize) {
// At this point, if there's a number of bits not multiple of 8,
// there are some bits that have not
// been writter. Not sure how you would like to handle it.
// One option is to assume that bits with 0 up to
// the next multiple of 8... but it all depends on what you're representing.
}
file.write(byteArray,bytes);
答案 1 :(得分:1)
将表示位表示的输入8个字符转换为一个字节的函数。
char BitsToByte( const char in[8] )
{
char ret = 0;
for( int i=0, pow=128;
i<8;
++i, pow/=2;
)
if( in[i] == '1' ) ret += pow;
return ret;
}
我们遍历传递给函数的数组(大小为8,原因很明显),并根据它的内容增加返回值(数组中的第一个元素代表最旧的位)。 pow
设置为128,因为2^(n-1)
是第n位的值。
答案 2 :(得分:0)
一种方式:
/** Converts 8 bytes to 8 bits **/
unsigned char BinStrToNum(const char a[8])
{
return( ('1' == a[0]) ? 128 : 0
+ ('1' == a[1]) ? 64 : 0
+ ('1' == a[2]) ? 32 : 0
+ ('1' == a[3]) ? 16 : 0
+ ('1' == a[4]) ? 8 : 0
+ ('1' == a[5]) ? 4 : 0
+ ('1' == a[6]) ? 2 : 0
+ ('1' == a[7]) ? 1 : 0);
);
};
以您提到的任何格式保存;或发明自己的!
int main()
{
rCode=0;
char *a = "10101010";
unsigned char byte;
FILE *fp=NULL;
fp=fopen("data.xyz", "wb");
if(NULL==fp)
{
rCode=errno;
fprintf(stderr, "fopen() failed. errno:%d\n", errno);
goto CLEANUP;
}
byte=BinStrToNum(a);
fwrite(&byte, 1, 1, fp);
CLEANUP:
if(fp)
fclose(fp);
return(rCode);
}
答案 3 :(得分:0)
你可以很容易地将它们转换成一个字节,如下所示:
byte x = (s[3] - '0') + ((s[2] - '0') << 1) + ((s[1] - '0') << 2) + ((s[0] - '0') << 3);
在我的例子中,我只移动了一个半字节或4位。您可以展开示例以移动整个字节。这个解决方案比循环更快。