打开文件
1
| FILE *freopen(const char *pathname, const char *mode, FILE *stream);
|
pathname:可以填写相对路径或绝对路径
stream:文件流
mode:模式(重点)
mode |
含义 |
文件不存在 |
文件存在 |
r |
只读 |
防护NULL(错误) |
从文件头开始读取 |
w |
清空写入 |
创建新文件 |
清空文件内容,从头开始写入 |
a |
追加写入 |
创建新文件 |
在文件末尾追加内容 |
r+ |
读写 |
防护NULL(错误) |
从文件头开始读写 |
w+ |
读写清空 |
创建新文件 |
清空文件内容,从头开始读写 |
a+ |
读写追加 |
创建新文件 |
在文件末尾追加内容,但允许读写 |
上面是以文本形式进行操作,如果你想以二进制形式操作文件,只需要在 mode 后面添加 b 即可。
关闭文件
1
| int fclose(FILE *stream);
|
文件流不再需要使用,记得用 fclose 关闭。
读写文件
文本
(一)读写单个字符
1 2 3
| int fgetc(FILE *stream);
int fputc(int c, FILE *stream);
|
示例程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| void readFile(const char* path) { FILE* src = fopen(path, "r"); if (!src) { fprintf(stderr, "src fopen failed!!!"); exit(-1); }
FILE* dst = fopen("b.txt", "w"); if (!dst) { fprintf(stderr, "dst fopen failed!!!"); exit(-1); }
char c; while ((c = fgetc(src)) != EOF) { if ((c >= 'a' && c <= 'm') || (c >= 'A' && c <= 'M')) { fputc(c + 13, dst); } else if ((c >= 'n' && c <= 'z') || (c >= 'N' && c <= 'Z')) { fputc(c - 13, dst); } else { fputc(c, dst); } }
fclose(src); fclose(dst); }
|
(二)读写一行
1 2 3
| char *fgets(char *s, int size, FILE *stream);
int fputs(const char *s, FILE *stream);
|
示例程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #define MAX_LEN 128 void readFile(const char* path) { FILE* src = fopen(path, "r"); if (!src) { fprintf(stderr, "src fopen failed!!!"); exit(-1); }
FILE* dst = fopen("b.txt", "w"); if (!dst) { fprintf(stderr, "dst fopen failed!!!"); exit(-1); }
char* line[MAX_LEN]; char* message[MAX_LEN]; int index = 1; while ((fgets(line, MAX_LEN, src) != NULL)) { sprintf(message, "%d. %s", index, line); fputs(message, dst); index++; }
fclose(src); fclose(dst); }
|
(三)格式化地读写
1 2 3
| int fscanf(FILE *stream, const char *format, ...);
int fprintf(FILE *stream, const char *format, ...);
|
示例程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| #define MAX_LEN 128 #define NAME_LEN 20
typedef struct student { int id; char name[NAME_LEN]; char sex; int chinese; int math; int english; } Student;
void readFile(const char* path) { FILE* src = fopen(path, "r"); if (!src) { fprintf(stderr, "src fopen failed!!!"); exit(-1); }
FILE* dst = fopen("b.txt", "w"); if (!dst) { fprintf(stderr, "dst fopen failed!!!"); exit(-1); } for (;;) { Student s; int n = fscanf(src, "%d%s %c%d%d%d", &s.id, s.name, &s.sex, &s.chinese, &s.math, &s.english); if (n != 6) break;
s.chinese = s.chinese * 0.85; s.math = s.math * 0.9; s.english = s.english * 0.8;
fprintf(dst, "%d %s %c %d %d %d\n", s.id, s.name, s.sex, s.chinese, s.math, s.english); }
fclose(src); fclose(dst); }
|
二进制
1 2 3
| size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
|
fread 的返回值是读取的大小,这个返回值将作为 fwrite size 参数。不然读取超出已读的长度会出现错误。
示例程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #define MAX_LEN 128 void readFile(const char* path) { FILE* src = fopen(path, "r"); if (!src) { fprintf(stderr, "src fopen failed!!!"); exit(-1); }
FILE* dst = fopen("b.txt", "w"); if (!dst) { fprintf(stderr, "dst fopen failed!!!"); exit(-1); }
char* data[MAX_LEN]; int n = 0; while ((n = fread(data, 1, MAX_LEN, src)) > 0) { fwrite(data, 1, n, dst); }
fclose(src); fclose(dst); }
|
移动文件位置
1 2 3 4 5
| int fseek(FILE *stream, long offset, int whence);
long ftell(FILE *stream);
void rewind(FILE *stream);
|
其中 whence 参数有三个取值:
SEEK_SET
: 文件开头,表示从文件的起始位置移动文件指针。
SEEK_CUR
: 当前文件指针位置,表示从当前指针位置移动。
SEEK_END
: 文件末尾,表示从文件末尾开始移动。
示例程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| char* readFile(const char* path) { FILE* fp = fopen(path, "r"); if (!fp) { exit(-1); }
fseek(fp, 0, SEEK_END); long int len = ftell(fp); rewind(fp);
if (len == -1) { exit(-1); }
char* data = malloc(sizeof(char) * (len + 1)); if (!data) { exit(-1); }
size_t reNum = fread(data, 1, len, fp); if (reNum != len) { free(data); fclose(fp); exit(-1); } data[reNum] = '\0';
fclose(fp); return data; }
|
由于我们要把某个文件内容全部读取到数组中,但是我们又不知道要申请多大的空间,利用 刚刚介绍的方法就能轻松解决这个问题:
1 2 3
| fseek(fp, 0, SEEK_END); long int len = ftell(fp); rewind(fp);
|