在 C 语言中读取二进制文件
本文将演示如何在 C 语言中读取二进制文件的多种方法。
使用 fread
函数读取 C 语言中的二进制文件
fread
是 C 标准库输入/输出设施的一部分,可以利用它从普通文件中读取二进制数据。C 标准库实现了一个用户缓冲 I/O 以及一个独立于平台的解决方案来处理二进制文件数据的读/写。标准 I/O 函数在文件指针上操作,而不是文件描述符。FILE*
流由 fopen
函数检索,该函数将文件路径作为字符串常量和打开它们的模式。文件的模式指定了打开文件是读、写还是追加。不过要注意,每个模式字符串可以包含字母 b
来明确指定二进制文件模式,这可能会被一些非 UNIX 系统解释为对文本和二进制文件的不同处理。
在 fopen
返回文件指针后,我们可以调用 fread
函数来读取二进制流。fread
需要四个参数,其中第一个参数是 void
指针,指向读取的字节应该存储的位置。接下来的两个参数指定需要从给定文件中读取的数据项的大小和数量。最后,函数的第四个参数是应该从其中读取数据的 FILE
指针。在下面的例子中,我们打开并向名为 input.txt
的文件写入一些任意字节。然后,我们关闭该文件并再次打开它进行读取。
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
const uint8_t data[] =
{ 0x54, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79,
0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x74,
0x6f, 0x20, 0x62, 0x65, 0x20, 0x77, 0x72, 0x69, 0x74,
0x74, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x69,
0x6c, 0x65 };
const char* filename = "input.txt";
int main(void) {
FILE* output_file = fopen(filename, "wb+");
if (!output_file) {
perror("fopen");
exit(EXIT_FAILURE);
}
fwrite(data, 1, sizeof data, output_file);
printf("Done Writing!\n");
fclose(output_file);
FILE* in_file = fopen(filename, "rb");
if (!in_file) {
perror("fopen");
exit(EXIT_FAILURE);
}
struct stat sb;
if (stat(filename, &sb) == -1) {
perror("stat");
exit(EXIT_FAILURE);
}
char* file_contents = malloc(sb.st_size);
fread(file_contents, sb.st_size, 1, in_file);
printf("read data: %s\n", file_contents);
fclose(in_file);
free(file_contents);
exit(EXIT_SUCCESS);
}
输出:
Done Writing!
read data: Temporary string to be written to file
使用 read
函数读取 C 语言中的二进制文件
或者,我们可以使用 read
函数,它本质上是一个系统调用。请注意,read
对文件描述符起作用;因此文件应该用 open
系统调用打开。它需要额外的两个参数,表示读取的数据将被存储的 void
指针和要从文件中读取的字节数。请注意,我们正在读取文件的全部内容,并使用 malloc
函数为其动态分配内存。利用 stat
系统调用来查找文件大小。
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
const uint8_t data[] =
{ 0x54, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79,
0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x74,
0x6f, 0x20, 0x62, 0x65, 0x20, 0x77, 0x72, 0x69, 0x74,
0x74, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x69,
0x6c, 0x65 };
const char* filename = "input.txt";
int main(void) {
FILE* output_file = fopen(filename, "wb+");
if (!output_file) {
perror("fopen");
exit(EXIT_FAILURE);
}
fwrite(data, 1, sizeof data, output_file);
printf("Done Writing!\n");
fclose(output_file);
int fd = open(filename, O_RDONLY);
if (fd == -1) {
perror("open\n");
exit(EXIT_FAILURE);
}
struct stat sb;
if (stat(filename, &sb) == -1) {
perror("stat");
exit(EXIT_FAILURE);
}
char* file_contents = malloc(sb.st_size);
read(fd, file_contents, sb.st_size);
printf("read data: %s\n", file_contents);
close(fd);
free(file_contents);
exit(EXIT_SUCCESS);
}
输出:
Done Writing!
read data: Temporary string to be written to file
Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.
LinkedIn