出于某种原因,当我打开一个文件并在Python和C中逐字节地读取它并尝试打印结果时,我会混入随机字符/数据。
例如,当我读取PNG图像的前8个字节时,如下例所示:
/* Test file reading and see if there's random data */
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define PNG_BYTES_TO_CHECK 8
int
main(void)
{
char fname[] = "../images/2.png";
FILE *fp = fopen(fname, "rb");
if (fp == NULL) abort();
char *buffer = (char *)malloc(PNG_BYTES_TO_CHECK);
if (fread(buffer, 1, PNG_BYTES_TO_CHECK, fp) != PNG_BYTES_TO_CHECK)
abort();
unsigned i;
for (i = 0; i < PNG_BYTES_TO_CHECK; ++i) printf("%x ", buffer[i]);
printf("\n");
free(buffer); fclose(fp);
return 1;
}
我把这个垃圾带到stdout:
ffffff89 50 4e 47 d a 1a a
但是当我用十六进制编辑器打开文件时,字节非常好(它是一个有效的PNG签名):
关于可能导致这种情况的任何想法?我没有Python的例子,但我记得几天前我在字节级处理文件并打印内容时会遇到重复的mumbo jumbo。
答案 0 :(得分:1)
png spec表示png文件应始终以字节137 80 78 71 13 10 26 10
开头。有符号字节的最大值为127,这意味着第一个字节的值溢出并变为-119(如果这令人困惑,请查看the way negative numbers are represented)。然后,您将其打印为无符号十六进制整数。为此,签名字节将提升为整数。同样,由于表示负数的方式,值为-119的4字节整数具有以下二进制表示:11111111111111111111111110001001
。 %x
是无符号十六进制值的格式说明符。因为它认为你给它的值是无符号的,所以它不会将该二进制解释为好像它被表示为负数。如果您将11111111111111111111111110001001
转换为十六进制,那么您会看到它是ffffff89
。
tl;博士:文件没有任何问题。你只是忘了让你的字节无符号。