在 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