C 一次读取一个二进制文件1字节

C 一次读取一个二进制文件1字节,c,file,io,binary,C,File,Io,Binary,我试图一次读取一个1字节的二进制文件,在互联网上搜索了几个小时后,我仍然无法检索到任何东西,除了垃圾和/或seg故障。基本上,二进制文件的格式是一个列表,长度为256项,每项为1字节(0到255之间的无符号整数)。我试图使用fseek和fread跳转到二进制文件中的“索引”并检索该值。我目前拥有的代码: unsigned int buffer; int index = 3; // any index value size_t indexOffset = 256 * index; fseek(

我试图一次读取一个1字节的二进制文件,在互联网上搜索了几个小时后,我仍然无法检索到任何东西,除了垃圾和/或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("%d\n", buffer);

现在这段代码给了我随机的垃圾数和seg错误。有关如何使其正常工作的任何提示?

在您的代码中,您试图读取256个字节到一个int的地址。如果您想一次读取一个字节,请调用
fread(&buffer,1,1,file)(请参阅)

但一个更简单的解决方案是声明一个字节数组,一起读取,然后进行处理

unsigned char buffer; // note: 1 byte
fread(&buffer, 1, 1, file);

是时候读我相信的人了

您试图将256个字节读入名为“buffer”的4字节整数变量。您正在覆盖下一个252字节的其他数据

似乎
缓冲区
应该是
无符号字符缓冲区[256]
或者您应该执行
fread(&buffer,1,1,f)
,在这种情况下
buffer
应该是
unsigned char buffer

或者,如果您只需要一个字符,您可以将
缓冲区
保留为
int
(不需要无符号,因为C99保证了普通int的合理最小范围),然后简单地说:

buffer = fgetc(f);

目前的代码有几个问题

fread的原型是:

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
您已将大小设置为256(字节),计数设置为1。这很好,这意味着“读取一个256字节的块,将其放入缓冲区”

但是,您的缓冲区大约有2-8字节长(或者至少比256字节小得多),因此存在缓冲区溢出。您可能想使用fred(缓冲区,1,1,文件(&buffer)

此外,您正在将字节数据写入int指针。这将在单端(事实上是小端)上起作用,所以你在英特尔体系结构上会很好,从中学习坏习惯,总有一天会回来咬你

尽量只将字节数据写入字节组织的存储器,而不要写入int或float。

您将字节与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次。

每次读取一个字节的文件将产生巨大的I/O开销。更好的方法是将整个文件读入缓冲区(因为它只有256个字节),然后分别处理存储在缓冲区中的每个字节。@titaniumdecoy-我相信I/O管理器会在现代操作系统上缓冲读取。缓冲区类型为unsigned int。未初始化,因此在
fread(&buffer,1,1,file)之后您将得到一个数字,其中24位将包含一些随机值。如何声明一个字节数组并一起读取?谢谢@tommy.carstensen-请看下面我的答案:)我被告知操作系统实际上执行缓冲。无论如何,如果不是这样的话,我很确定光碟控制器做了一点缓冲。是的,但是调用输入函数总是有开销指令;可能包括重新加载指令缓存。为了提高性能,应该减少此开销-因此每个请求更多的数据更有效。如果文件只有255个字节,而您尝试读取256个字节,会发生什么情况?你能循环读取整个文件吗?如果你需要256个字节,但只有253个字节,那么
fread
函数将返回253个字节。可以读取多个块,直到读取整个文件;这是一门古老的艺术,因为内存容量有限。如果您正在读取文件,我建议使用512或1024的倍数,因为这是扇区的大小。