2017-09-27 869 views
1

显示他们我有一个包含key.hex文件:从文件中读取十六进制值,并用C

00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 

为十六进制值。我试着去阅读他们,并立即打印出来:

unsigned char key[16]; 
FILE *secretkey; 
secretkey = fopen("key.hex", "r+"); 
fgets(key, 16, secretkey); 
int j = 0; 
for(j = 0; j < sizeof(key) ; j++) { 
    printf("%02x ", key[j]); 
} 

然而,当我得到以下的输出:

00 01 02 03 04 05 06 07 08 09 0a 00 80 d2 73 b7 

为什么输出不对应于文件的内容?

+1

您将15 ***个字符***读入'key',而不是全行,并且您将其读作***字符串***而不是单独的整数。 –

+4

在典型的ASCII环境中,'0a'是换行('LF'或'\ n'),它会终止你的'fgets'调用,所以你不会读剩下的字节。使用'fread'而不是'fgets'。 –

+4

这些数字是以文本还是以二进制值的形式存储的? – Gerhardh

回答

2

保罗 - [R:
在典型的ASCII环境0a是换行(LF\n),终止你与fgets调用,所以你不读其余的字节。
使用fread而不是fgets。

E.g.
(从代码中最相关的线由BLUEPIXY,这是一个完整的演示中评论链接):

secretkey = fopen("key.hex", "r+b"); 
fread(key, 1, sizeof key, secretkey); 

(这汇集了来自两点意见,其中的每一个将是一个不错的答案的答案,我提供给。如果删除任何两位作者的让自己的答案,并要求我)

1

你说该文件包含这些十六进制值:

00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 

所以在F ILE恰恰包含16个字节:第一个具有价值0x00,第二个值0x01

这就是所谓的有二进制文件。这不是一个文本文件。该文件中几乎没有普通的可打印字符。如果我们要将该文件打印到屏幕上,我们会看到奇怪的字形和垃圾,或者什么都没有。

fgets函数用于从文本文件中读取文本的一行。具体来说,它读取包括行尾指示在内的字符。在Unix/Linux系统上,行尾指示是换行字符。在ASCII中,换行符具有字符代码0x0a。此外,由于fgets函数旨在处理文本,因此它通过在输出缓冲区末尾附加空字节(0x00或)将其读取的文本转换为C字符串。

那么发生了什么事fgets只读取了文件中的前11个字符,包括0A,并将这些字符加上终止空字符写入key数组。所以它只填充阵列的前12个单元。最后4个字符保留了首次定义数组时未包含的初始化垃圾值。 (在这种情况下,它看起来像他们80d273b7。)

但你真的想在这种情况下该怎么做,它看起来像,读16个原始字节,而不承担他们”重新编写文本,不需要查找换行符,也不会导致null结束。这是一个非常不同的要求,但事实证明,另一个标准库函数完全符合你的要求:fread

因此重写代码是这样的:

FILE *secretkey; 
secretkey = fopen("key.hex", "rb"); 
if(secretkey == NULL) { 
    fprintf(stderr, "can't open %s\n", "key.hex"); 
    exit(1); 
} 
int r = fread(key, 1, 16, secretkey); 
if(r != 16) { 
    fprintf(stderr, "error reading key: read %d chars, expected %d\n", r, 16); 
    exit(1); 
} 
int j; 
for(j = 0; j < sizeof(key) ; j++) { 
    printf("%02x ", key[j]); 
} 

你会发现,我还添加了代码检查fread没有实际读取的16个字节预期。我还添加了代码来检查fopen调用是否成功地打开了“key.hex”文件。此外,我更改了fopen调用以二进制模式打开文件("rb"),并删除了+修改器,您可能不想这样做。

作为一个侧面说明,如果你想要做的更好的错误处理,打开文件失败时,它总是一个好主意,打印指示一个更具描述性错误消息,为什么文件无法打开:

if(secretkey == NULL) { 
    fprintf(stderr, "can't open %s: %s\n", "key.hex", strerror(errno)); 
    exit(1); 
} 

要做到这一点,你还必须包含头文件为errno价值<string.h>strerror()功能,<errno.h>

相关问题