C语言 一次读取一个二进制文件 1 个字节
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6093224/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Reading a binary file 1 byte at a time
提问by RogerB
I am trying to read a binary file in C 1 byte at a time and after searching the internet for hours I still can not get it to retrieve anything but garbage and/or a seg fault. Basically the binary file is in the format of a list that is 256 items long and each item is 1 byte (an unsigned int between 0 and 255). I am trying to use fseek and fread to jump to the "index" within the binary file and retrieve that value. The code that I have currently:
我试图一次读取一个 C 1 字节的二进制文件,在互联网上搜索了几个小时后,我仍然无法让它检索除垃圾和/或段错误之外的任何内容。基本上,二进制文件采用列表格式,长度为 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);
Right now this code is giving me random garbage numbers and seg faulting. Any tips as to how I can get this to work right?
现在这段代码给了我随机的垃圾数和段错误。有关如何使其正常工作的任何提示?
回答by MByD
In your code you are trying to read 256 bytes to the address of one int. If you want to read one byte at a time, call fread(&buffer, 1, 1, file);(See fread).
在您的代码中,您试图将 256 个字节读取到一个 int 的地址。如果您想一次读取一个字节,请调用fread(&buffer, 1, 1, file);(参见fread)。
But a simpler solution will be to declare an array of bytes, read it all together and process it after that.
但是一个更简单的解决方案是声明一个字节数组,将其全部读取并在此之后进行处理。
回答by Thomas Matthews
Your confusing byteswith int. The common term for a byteis an unsigned char. Most bytes are 8-bits wide. If the data you are reading is 8 bits, you will need to read in 8 bits:
你与int混淆的字节。字节的通用术语是unsigned char。大多数字节是 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
The reason for reading all the data into memory is to keep the I/O flowing. There is an overhead associated with each input request, regardless of the quantity requested. Reading one byte at a time, or seeking to one position at a time is the worst case.
将所有数据读入内存的原因是为了保持 I/O 流动。无论请求的数量如何,每个输入请求都有相关的开销。一次读取一个字节,或一次寻找一个位置是最坏的情况。
Here is an example of the overhead required for reading 1 byte:
以下是读取 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.
In your program design, the above steps will be repeated 256 times. With everybody's suggestion, the line marked with "-->" will read 256 bytes. Thus the overhead is executed only once instead of 256 times to get the same quantity of data.
在您的程序设计中,上述步骤将重复 256 次。在大家的建议下,标有“-->”的行将读取256个字节。因此,开销只执行一次而不是 256 次来获得相同数量的数据。
回答by c-smile
unsigned char buffer; // note: 1 byte
fread(&buffer, 1, 1, file);
It is time to read mans I believe.
是时候阅读我相信的男人了。
回答by DigitalRoss
You are trying to read 256 bytes into a 4-byte integer variable called "buffer". You are overwriting the next 252 bytes of other data.
您正在尝试将 256 个字节读入一个名为“缓冲区”的 4 字节整数变量。您正在覆盖接下来的 252 个字节的其他数据。
It seems like buffershould either be unsigned char buffer[256];or you should be doing fread(&buffer, 1, 1, f)and in that case buffershould be unsigned char buffer;.
看起来buffer应该是unsigned char buffer[256];或者你应该做的fread(&buffer, 1, 1, f),在那种情况下buffer应该是unsigned char buffer;。
Alternatively, if you just want a single character, you could just leave bufferas int(unsignedis not needed because C99 guarantees a reasonable minimum range for plain int) and simply say:
或者,如果您只想要一个字符,则可以保留buffer为int(不需要unsigned因为 C99 保证了普通 int 的合理最小范围)并简单地说:
buffer = fgetc(f);
回答by Vatine
Couple of problems with the code as it stands.
代码存在一些问题。
The prototype for fread is:
fread 的原型是:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
You've set the size to 256 (bytes) and the count to 1. That's fine, that means "read one lump of 256 bytes, shove it into the buffer".
您已将大小设置为 256(字节)并将计数设置为 1。这很好,这意味着“读取一组 256 字节,将其推入缓冲区”。
However, your buffer is on the order of 2-8 bytes long (or, at least, vastly smaller than 256 bytes), so you have a buffer overrun. You probably want to use fred(&buffer, 1, 1, file).
但是,您的缓冲区大约有 2-8 个字节长(或者,至少远小于 256 个字节),因此您会遇到缓冲区溢出。您可能想要使用 fred(&buffer, 1, 1, file)。
Furthermore, you're writing byte data to an int pointer. This will work on one endian-ness (small-endian, in fact), so you'll be fine on Intel architecture and from that learn bad habits tha WILL come back and bite you, one of these days.
此外,您正在将字节数据写入 int 指针。这将适用于一种字节序(实际上是小字节序),因此您在英特尔架构上会很好,并从中学习坏习惯,然后会回来咬你,这些日子之一。
Try real hard to only write byte data into byte-organised storage, rather than into ints or floats.
努力只将字节数据写入字节组织的存储中,而不是写入整数或浮点数。

