读写二进制文件
打开文件
fopen()
函数用来创建一个新文件或者打开一个已有的文件,该函数返回一个 FILE 对象的指针,函数原型:
#include <stdio.h>
FILE *fopen(const char *pathname, const char *mode);
pathname
是指向文件路径的字符串指针,mode
访问模式包括以下几种:
Mode | Description |
---|---|
r | 以读方式打开文件 |
w | 以写方式打开文件,如果文件不存在将创建一个新文件,如果文件已经存在则截断为零长度,重新写入 |
a | 以追加方式打开文件(在文件尾部写入),如果文件不存在将创建一个新文件 |
r+ | 以读写方式打开文件 |
w+ | 以读写方式打开文件,如果文件不存在将创建一个新文件,否则截断为零长度 |
a+ | 以读与追加方式打开文件,如果文件不存在将创建一个新文件,输出总是添加到文件尾部 |
访问模式字符串还可以包含字母 “b” 作为最后一个字符或上述两个字符字符串中任何一个字符之间的字符。这完全是为了兼容 C89;在所有符合 POSIX 的系统上忽略 “b” 字符,包括 Linux。(其他系统可能会以不同的方式处理文本文件和二进制文件,如果您对二进制文件进行 I/O 操作,并且希望您的程序可以移植到非UNIX环境,则添加“b”可能是一个好主意。)
二进制 I/O 函数
读取函数
#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
从给定流 stream 读取数据到 ptr 所指向的数组中。
- ptr – 指向带有最小尺寸 size*nmemb 字节的内存块的指针。
- size – 读取的每个元素的大小,以字节为单位。
- nmemb – 元素的个数,每个元素的大小为 size 字节。
- stream – 指向 FILE 对象的指针,该 FILE 对象指定了一个输入流。
当执行成功时,fread()
返回读取到的数据大小,该大小仅当 size 为 1 时等于传输的字节数。如果发生错误,或到达文件结尾时,返回值为短计数(或零)。
fread()
不区分文件结尾和错误,调用者必须使用 feof()
和 ferror()
来确定发生了什么。
示例代码:
#include <stdio.h>
#include <stdint.h> // included for uint8_t
int main(int argc, char const *argv[]) {
uint8_t buf[4096] = {0x00};
FILE *fp = fopen("/usr/bin/prince", "r");
size_t size = fread(buf, sizeof(uint8_t), sizeof(buf), fp);
fclose(fp);
return 0;
}
检查文件结尾 (end-of-file)
#include <stdio.h>
int feof(FILE *stream);
函数 feof()
测试指向流的文件结束指示符(end-of-file indicator),如果设置了,则返回非零值。文件指示符只能通过函数 clearerr()
清除。
通俗地理解,就是在二进制文件读取过程中,通过 feof()
判断是否已经到达文件结尾。所以上面示例的完整版将类似这样:
#include <stdio.h>
#include <stdint.h> // included for uint8_t
static void print_data(const uint8_t *data, size_t len) {
for (size_t i = 0; i < len; ++i) {
if (i != 0 && i % 16 == 0) printf("\n");
printf("%02x ", data[i]);
}
printf("\n");
}
int main(int argc, char const *argv[])
{
uint8_t buf[4096] = {0x00};
size_t size = 0;
FILE *fp = fopen("/usr/bin/xxd", "r");
if (fp == NULL) return 1;
while (!feof(fp)) {
size = fread(buf, sizeof(uint8_t), sizeof(buf), fp);
print_data(buf, size);
// do something...
}
fclose(fp);
return 0;
}
写入函数
#include <stdio.h>
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
把 ptr 所指向的数组中的数据写入给定的 stream 流中。
- ptr – 指向需要写入到文件中的数组的指针
- size – 写入的每个元素的大小,以字节为单位
- nmemb – 元素的个数,每个元素的大小为 size 字节
- stream – 指向 FILE 对象的指针,该 FILE 对象指定了一个输出流。
当执行成功时,fwrite()
返回写入到文件的数据大小,该大小仅当 size 为 1
时等于传输的字节数。如果发生错误,返回值与 size*nmemb
不相等。
示例代码:
#include <stdio.h>
#include <stdint.h> // included for uint8_t
int main(int argc, char const *argv[]) {
uint8_t buf[8] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
FILE *fp = fopen("/tmp/hello.bin", "w");
size_t size = fwrite(buf, sizeof(uint8_t), sizeof(buf), fp);
fclose(fp);
return 0;
}
欢迎关注我的公众号:飞翔的小黄鸭
也许会发现不一样的风景
△
\triangle
△ C/C++获取文件大小
▽
\bigtriangledown
▽ Linux C/C++ 处理命令行参数