一、标准I/O和文件I/O的区别
1. 标准I/O分为全缓冲,行缓冲,不缓冲三种形式;文件I/O为不带缓冲的I/O。
2. 标准I/O遵循ANSI C标准,一般只需包含stdio.h头文件 ;文件I/O一般遵循POSIX标准。
3. POSIX标准包含C99标准(ANSI C)。
4. Linux的glibc库既包含标准C库,也包含POSIX标准中定义的函数。
二、标准I/O的用法
1. fopen
声明:FILE *fopen(const char *path, const char *mode);关于第二个参数mode的含义:
1.1 "r":以只读方式打开文件,文件不存在时,返回错误。
1.2 "r+":以读写方式打开文件,文件不存在时,返回错误。文件存在时,文件内容被清空。
1.3 "w":以只写方式打开文件,文件不存在时,创建文件;文件存在时,文件内容被清空。
1.4 "w+":以读写方式打开文件,文件不存在时,创建文件;文件存在时,文件内容被清空。
1.5 "a":以追加写方式打开文件,文件不存在时,创建文件;文件存在时,文件内容不会被清空。
1.6 "a+":以读写方式打开文件,文件不存在时,创建文件;文件存在时,文件内不被清空。读操作起始位置在文件开头,写操作起始位置在文件结尾。
2. fgets
声明:char *fgets(char *s, int size, FILE *stream);
2.1 作用:
读取文件中的一行数据。
2.2 返回值:
2.2.1 成功时,返回读取的字符串的起始位置。
2.2.2 失败时,返回NULL。
2.2.3 读取到文件结尾时,返回NULL。可通过feof(fp);判断,该函数返回非0时,表示读到文件结尾。
2.3 参数size说明:
2.3.1 指定最多读取(size - 1)个字节到缓冲区"s"中。预留一个字节存储'\0'。
2.3.2 文件中的换行符也会被读取出来。
2.3.3 当文件中一行数据过长时,第一fgets没有读取完,第二次fgets调用继续读取该行剩余数据。
3. fread / fwrite示例代码如下:
#include <stdio.h>
struct test_data {
int a;
int b;
};
int main(int argc, char *argv[])
{
int ret = 0;
struct test_data arr[3];
FILE *fp = NULL;
fp = fopen("./test.file", "r+");
if (NULL == fp) {
perror("fopen");
return -1;
}
memset(arr, 0, sizeof(arr));
arr[0].a = 11;
arr[0].b = 12;
arr[1].a = 21;
arr[1].b = 22;
arr[2].a = 31;
arr[2].b = 32;
ret = fwrite(arr, sizeof(struct test_data), sizeof(arr) / sizeof(arr[0]), fp);
perror("fwrite");
printf("ret is %d\n", ret);
printf("-------------------------------------------\n");
/*
疑问:仅进行了写操作,为什么读指针也向前移动了???
*/
printf("ftell() is %u\n", ftell(fp));
//fseek(fp, SEEK_SET, 0);
memset(arr, 0, sizeof(arr));
ret = fread(arr, sizeof(struct test_data), sizeof(arr) / sizeof(arr[0]), fp);
perror("fread");
printf("ret is %d\n", ret);
printf("a0 = %d, b0 = %d\n", arr[0].a, arr[0].b);
printf("a1 = %d, b1 = %d\n", arr[1].a, arr[1].b);
printf("a2 = %d, b2 = %d\n", arr[2].a, arr[2].b);
if (NULL != fp) {
fclose(fp);
fp = NULL;
}
return ret;
}