将字节转换为位,并将二进制数据写入文件



假设我有一个字符数组,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++]);
    }
}

这就是我如何编码以获得最终输出。

不完全确定如何得到表示值的二进制表示的字符串,但是,您可以使用std::strtoul等标准函数从字符串(以任意基数)中获取整数值。

该函数提供一个无符号长值,因为您知道您的值在0-255范围内,所以可以将其存储在无符号字符中:

无符号字符v=(无符号字符)(std::strtoul(binary_string_value.c_str(),0,2)&0xff);

将其写入磁盘,您可以使用流写入

我应该用哪种文件格式保存输出。txt或.dat或.bin?

请记住,扩展名(.txt、.dat或.bin)并没有真正强制要求格式(即内容的结构)。扩展名是常用的惯例,用于表示您正在使用一些众所周知的格式(在某些操作系统/环境中,它驱动哪个程序最能处理该文件的配置)。由于这是您的文件,因此由您定义实际格式。。。并用你最喜欢的任何扩展名(甚至没有扩展名)命名文件(或者换句话说,任何最能代表你的内容的扩展名),只要它对你和那些将使用你的文件的人有意义。

编辑:其他详细信息

假设我们有一个一定长度的缓冲区,用于存储字符串"0"one_answers"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); 

将表示位表示的输入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)进行迭代,并根据其内容增加返回值(数组中的第一个元素表示最旧的位)。CCD_ 1被设置为128,因为CCD_。

您可以很容易地将它们转换为一个字节,如下所示:

byte x = (s[3] - '0') + ((s[2] - '0') << 1) + ((s[1] - '0') << 2) + ((s[0] - '0') << 3);

在我的例子中,我只移动了一个半字节,即4位。您可以展开此示例来移动整个字节。这个解决方案将比循环更快。

单向:

/** 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:%dn", errno);
      goto CLEANUP;
      }
   byte=BinStrToNum(a);
   fwrite(&byte, 1, 1, fp);
CLEANUP:
   if(fp)
      fclose(fp);
   return(rCode);
   }

相关内容

  • 没有找到相关文章

最新更新