我试图一次读取C1字节的二进制文件,在互联网上搜索了几个小时后,我仍然无法检索到任何内容,只有垃圾和/或seg错误。基本上,二进制文件是一个256项长的列表格式,每个项都是1个字节(0到255之间的无符号整数)。我正在尝试使用fseek和fread跳转到二进制文件中的"索引"并检索该值。我目前拥有的代码:
unsigned int buffer;
int index = 3; // any index value
size_t indexOffset = 256 * index;
fseek(file, indexOffset, SEEK_SET);
fread(&buffer, 256, 1, file);
printf("%dn", buffer);
现在,这段代码给了我随机垃圾数和seg错误。关于如何让它正常工作,有什么建议吗?
您将字节与int混淆。字节的常用术语是无符号字符。大多数字节都是8位宽。如果您正在读取的数据是8位,则需要读取8位:
#define BUFFER_SIZE 256
unsigned char buffer[BUFFER_SIZE];
/* Read in 256 8-bit numbers into the buffer */
size_t bytes_read = 0;
bytes_read = fread(buffer, sizeof(unsigned char), BUFFER_SIZE, file_ptr);
// Note: sizeof(unsigned char) is for emphasis
将所有数据读入内存的原因是为了保持I/O的流动性。无论请求的数量如何,每个输入请求都有相关的开销。一次读取一个字节,或者一次查找一个位置是最糟糕的情况。
以下是读取1字节所需开销的示例:
Tell OS to read from the file.
OS searches to find the file location.
OS tells disk drive to power up.
OS waits for disk drive to get up to speed.
OS tells disk drive to position to the correct track and sector.
-->OS tells disk to read one byte and put into drive buffer.
OS fetches data from drive buffer.
Disk spins down to a stop.
OS returns 1 byte to your program.
在您的程序设计中,上述步骤将重复256次。根据大家的建议,标有"-->"的行将读取256字节。因此,开销仅执行一次而不是256次以获得相同数量的数据。
在代码中,您试图将256个字节读取到一个int的地址。如果您想一次读取一个字节,请调用fread(&buffer, 1, 1, file);
(请参阅fread)。
但一个更简单的解决方案是声明一个字节数组,将其全部读取,然后进行处理。
unsigned char buffer; // note: 1 byte
fread(&buffer, 1, 1, file);
我相信是时候读懂男人了。
目前的代码存在一些问题。
fread的原型是:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
您已将大小设置为256(字节),并将计数设置为1。这很好,这意味着"读取一块256字节,将其推入缓冲区"。
然而,您的缓冲区大约有2-8个字节长(或者,至少远小于256个字节),因此缓冲区溢出。您可能想要使用fred(&buffer,1,1,file)。
此外,您正在向int指针写入字节数据。这将适用于单端序(事实上是小端序),所以你会对英特尔体系结构很满意,从中学习到坏习惯,总有一天会反噬你。
尽量只将字节数据写入字节组织的存储中,而不是写入int或float。
您正试图将256个字节读取到一个名为"buffer"的4字节整数变量中。您正在覆盖接下来的252字节的其他数据。
看起来buffer
应该是unsigned char buffer[256];
,或者你应该做fread(&buffer, 1, 1, f)
,在这种情况下buffer
应该是unsigned char buffer;
。
或者,如果您只想要一个字符,可以将buffer
保留为int
(不需要无符号,因为C99保证了纯int的合理最小范围),然后简单地说:
buffer = fgetc(f);