【问题标题】:Parse Binary to Decimal将二进制解析为十进制
【发布时间】:2013-07-30 20:01:43
【问题描述】:

我目前正在编写一个程序,该程序存储一个“uint16_t”数值数组,然后将它们写入二进制文件。由于大小考虑,我写入二进制文件(因为我将处理大量数据)。到目前为止,这是我的代码:

static int sizebuf=5;
int main(int argc, const char *argv[]){
     uint16_t buff[sizebuf];
     for(int i=0; i<sizebuf; i++){
            buff[i]=i;
     }
     FILE *fpbin=fopen("test.bin","a+");
     fwrite(buff, sizeof(uint16_t), sizeof(buff)/sizeof(uint16_t), fpbin);
     rewind(fpbin);

     uint16_t buffer[sizebuf];
     fread(buff, sizeof(uint16_t), sizebuf, fpbin);
     for (int i = 0; i < 5; i++)
     {
         printf("%" PRIu16 "\n",buffer[i]);
     }
     fclose(fpbin);
     return 0;
 }

当我使用“hexdump”检查“test.bin”中的输出时,我得到以下信息:

 0000000 0000 0001 0002 0003 0004
 000000a

首先,我不太确定我是否理解第一个“000000”和最后一个“00000a”值的存在。其次,我怎样才能将这些值转换回小数(即恢复为原始数值)?我咨询过的消息来源之间的共识似乎意味着没有标准的方法来做到这一点(鉴于我正在处理通用二进制输出,我理解这一点),但是我可以处理我的特定数据以进行转换的方法是什么?

感谢您的帮助!


编辑: 添加“fread”代码后,我收到了以下输出:

5
0
10416
49150
0

【问题讨论】:

  • 只需使用fread 将值读回uint16_t。你是什​​么意思转换回ascii? printf 应该能够做到所有这些。
  • “返回到 Ascii 文本”——一开始就不是“ASCII 文本”。您的意思可能是“回到十进制表示法”。
  • 你确定最后一个000000a 不在下一行吗?
  • 感谢您的及时回复。我已经更新了上面的代码以反映 Bart 的建议。我还尝试了 '%d' 格式标识符。而且,是的,我的意思是回到十进制表示法。是的,00000a 在下一行。
  • 您的fread 代码声明了buffer,但随后读入buff,因此当您打印出buffer 的内容时,您正在打印未初始化的垃圾...

标签: c linux parsing binary ascii


【解决方案1】:

当您使用hexdump -xod -x 检查输出时,您会看到

0000000 0000 0001 0002 0003 0004
000000a

最左边的列是十六进制的偏移量。两个实用程序都输出一个没有任何数据的最终地址,以显示解析的字节数。

换句话说,输出包含0x0a=10 个字节,可以解释为五个16 位字:0x0000=0、0x0001=1、0x0002=2、0x0003= 3,和0x0004=4。

如果您只需要十六进制字,每行一个字,请使用od -v -An -w2 -t x2。对于十进制字,请使用od -v -An -w2 -t d2

有关输出的更多详细信息,请参阅 man 1 odman 1 hexdump

【讨论】:

    【解决方案2】:

    第一个000000 是文件的偏移量。由于该数据来自文件的开头,因此偏移量为0000000a 是总文件大小 - 在您的情况下为 10 个字节(5 个数组条目乘以每个条目 2 个字节)。通常,该行将位于数据的新行上;你确定你复制/粘贴正确吗?

    以下是我机器上的一些示例以及您的程序输出:

    $ hexdump test.bin # traditional hexdump output
    0000000 00 00 01 00 02 00 03 00 04 00                
    000000a
    
    $ hexdump -d test.bin  # two-byte decimal output
    0000000   00000   00001   00002   00003   00004                        
    000000a
    
    $ hexdump -x test.bin  # two-byte hexadecimal output 
    0000000    0000    0001    0002    0003    0004                        
    000000a
    

    如果你想从你的二进制文件中生成一些十进制输出,你需要提供一些格式化信息给 hexdump:

    $ hexdump -e '5/2 "%d " "\n"' test.bin 
    0 1 2 3 4
    

    或者,在您的程序中使用fprintf 让您的程序输出文本,而不是二进制数据。将fwrite 调用替换为:

     for (int i = 0; i < sizebuf; i++)
         fprintf(fpbin, "%d\n", buff[i]);
    

    进行更改后的输出:

    $ cat test.bin 
    0
    1
    2
    3
    4
    

    【讨论】:

    • 感谢您的回复。事实证明我将要处理大量数据,所以我希望先写入二进制文件,这样我就不会使用文件大小。我只是在寻找一种从我创建的二进制文件中获取原始十进制数据的方法。
    • 我认为我的回答解决了这个问题,还是我误解了?
    【解决方案3】:

    0000000 实际上是指行号。它不在二进制文件中,而是由您的十六进制转储应用程序生成。您的第二行将包含 00000010,表示每个行号最多有 16 个字节。

    每一行以换行结束,即ascii 0xa。每一行都将以此结束。

    将每个字节转换为数字,然后使用 itoa 获取 ascii 值。

    【讨论】:

    • OP 的程序没有生成换行符。
    • 000000a 是第二个“行号”。但是,这些并不是真正的行号,它们是十六进制偏移量。第一个字节在偏移量 0000000 处,在输出的最后一行之后,hexdump 程序显示一行没有内容,显示下一个字节的偏移量。
    猜你喜欢
    • 2018-12-14
    • 2023-03-15
    • 1970-01-01
    • 2012-06-26
    • 2020-04-25
    • 1970-01-01
    • 1970-01-01
    • 2017-05-23
    • 1970-01-01
    相关资源
    最近更新 更多