从文件中读取十六进制值,并用C
显示他们我有一个包含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
为什么输出不对应于文件的内容?
保罗 - [R:
在典型的ASCII环境0a
是换行(LF
或\n
),终止你与fgets调用,所以你不读其余的字节。
使用fread而不是fgets。
E.g.
(从代码中最相关的线由BLUEPIXY,这是一个完整的演示中评论链接):
secretkey = fopen("key.hex", "r+b");
fread(key, 1, sizeof key, secretkey);
(这汇集了来自两点意见,其中的每一个将是一个不错的答案的答案,我提供给。如果删除任何两位作者的让自己的答案,并要求我)
你说该文件包含这些十六进制值:
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个字符保留了首次定义数组时未包含的初始化垃圾值。 (在这种情况下,它看起来像他们80
,d2
,73
和b7
。)
但你真的想在这种情况下该怎么做,它看起来像,读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>
。
您将15 ***个字符***读入'key',而不是全行,并且您将其读作***字符串***而不是单独的整数。 –
在典型的ASCII环境中,'0a'是换行('LF'或'\ n'),它会终止你的'fgets'调用,所以你不会读剩下的字节。使用'fread'而不是'fgets'。 –
这些数字是以文本还是以二进制值的形式存储的? – Gerhardh