1. 为什么使用文件
为了使数据更长久的储存。
2. 什么是文件
文件包括程序文件和数据文件
程序文件:源文件,目标文件,可执行文件
数据文件:程序运行过程中可以进行读写的文件。
文件名包括3部分:文件路径,文件名和文件后缀。
3. 文件的打开和关闭
文件指针
每个文件在打开的时候,都会开辟一个文件信息区。这个文件信息区的类型为
FILE
类型,对于读写都是通过FILE
指针来实现的。
文件的打开和关闭
需要的头文件为
stdio.h
,文件打开后,等到不使用它的时候,不要忘记关闭文件。
open
第一个参数为文件系统名,第二个参数为文件访问的模式
访问模式如下:
返回类型为
FILE*
。文件访问成功返回指向新文件流的指针。失败返回空指针。
fclose
关闭文件,参数为
FILE*
类型的流。返回类型为int
有没有发现这个函数和
free
相似。
简单的使用一下
int main() { FILE* p = fopen("test.txt", "w"); if (p == NULL) { perror("fopen"); return 0; } fclose(p); p = NULL; return 0; }
int main() { FILE* p = fopen("test.txt", "r"); if (p == NULL) { perror("fopen"); return 0; } fclose(p); p = NULL; return 0; }
4. 文件的顺序读写
fgetc
参数为
FILE*
的流,功时为作为unsigned char
获得并转换为int
的字符,失败时为EOF
。例:
int main() { FILE* p = fopen("test.txt", "r"); if (p == NULL) { perror("fopen"); return 0; } int ch; while ((ch=fgetc(p))!=EOF) { printf("%c", ch); } fclose(p); p = NULL; return 0; }
fputc
写入字符
ch
到给定输出流stream
成功时,返回被写入字符。失败时,返回
EOF
例:
int main() { FILE* p = fopen("test.txt", "w"); if (p == NULL) { perror("fopen"); return 0; } char ch; for (ch = 'a'; ch <= 'z'; ch++) { fputc(ch, p); } fclose(p); p = NULL; return 0; }
fgets
从
stream
流中最多获得n-1
个字符到string
中。遇到换行符\n
或者是文件结束时停止分析。并返回srting
。若没有读取字符,返回空指针,不覆盖string
指向字符串的内容。
例:
int main() { FILE* p = fopen("test.txt", "r"); if (p == NULL) { perror("fopen"); return 0; } char arr[200]={0}; while (fgets(arr, 200, p)) { printf("%s", arr); } fclose(p); p = NULL; return 0; }
fputs
把字符串写入
stream
中成功时,返回非负值。失败时,返回
EOF
例:
int main() { FILE* p = fopen("test.txt", "w"); if (p == NULL) { perror("fopen"); return 0; } fputs("acd", p); fclose(p); p = NULL; return 0; }
fscanf
从文件流 stream 读取数据。
返回值和
scanf
的返回方式一样。
例:
int main() { FILE* p = fopen("test.txt", "r"); if (p == NULL) { perror("fopen"); return 0; } char arr[200] = { 0 }; fscanf(p,"%s",arr); printf("%s\n", arr); fclose(p); p = NULL; return 0; }
fprintf
写结果到文件流
stream
用法和
printf
的用法非常相似。
int main() { FILE* p = fopen("test.txt", "w"); if (p == NULL) { perror("fopen"); return 0; } fprintf(p, "%s", "哈哈哈"); fclose(p); p = NULL; return 0; }
fread
把流中的数据读入到数组中
size
为每个对象字节的大小
count
要读取的对象的个数。
例:
int main() { FILE* p = fopen("test.txt", "r"); if (p == NULL) { perror("fopen"); return 0; } char arr[200]={0}; fread(arr, 1, 100, p); printf("%s\n", arr); fclose(p); p = NULL; return 0; }
fwrite
把
buffer
指向里面的数据写到stream
流中
size
是一个对象的大小,count
为对象的个数
例:
int main() { FILE* p = fopen("test.txt", "w"); if (p == NULL) { perror("fopen"); return 0; } char arr[200] = "abcdefds"; fwrite(arr, 1, 20, p); fclose(p); p = NULL; return 0; }
sscanf
格式化读入
从
buffer
中的数据读入到后面的格式化中
例:
struct s { int age; char name[30]; }; int main() { struct s a; char arr[100]="20zhangsan"; sscanf(arr, "%d %s", &(a.age), a.name); return 0; }
sprintf
格式化写入
把格式化的数据写入到字符串中
例:
struct s { int age; char name[30]; }; int main() { struct s a={20,"zhangsan"}; char arr[100] = { 0 }; sprintf(arr, "%d %s", a.age, a.name); return 0; }
5. 文件的随机读写
fseek
设置文件流 stream 的文件位置指示器的指向
关于返回值,成功返回0,否则返回非零。
例:
int main() { FILE* p = fopen("test.txt", "w"); if (p == NULL) { perror("fopen"); return 0; } fputs("sscbcsd", p); fseek(p, 2, SEEK_SET); fputs("哈哈", p); fclose(p); p = NULL; return 0; }
ftell
例:
int main() { FILE* p = fopen("test.txt", "wb"); if (p == NULL) { perror("fopen"); return 0; } fseek(p, 2, SEEK_SET); long ret=ftell(p); printf("%d\n", ret); fclose(p); p = NULL; return 0; }
rewind
例:
int main() { FILE* p = fopen("test.txt", "wb"); if (p == NULL) { perror("fopen"); return 0; } fseek(p, 2, SEEK_SET); rewind(p); printf("%ld\n", ftell(p)); fclose(p); p = NULL; return 0; }
6. 文本文件和二进制文件
数据在内存中是怎么储存,在文件中就是怎么储存,这就是二进制文件。
把内存的数据转换成ASCII形式存储,这种就是文本文件。
7. 文件读取结束的判定
下面两个函数分别判断文件是以那种方式结束的,是错误原因导致的还是文件读完结束的。
ferror
若文件流已出现错误则为非零值,否则为 0
feof
若已抵达流尾则为非零值,否则为 0
例:
int main() { FILE* p = fopen("test.txt", "wb"); if (p == NULL) { perror("fopen"); return 0; } fseek(p, 2, SEEK_SET); rewind(p); printf("%ld\n", ftell(p)); if (feof(p)) printf("文件没有读取完\n"); else if (ferror(p)) printf("文件读取错误\n"); fclose(p); p = NULL; return 0; }
8. 文件缓冲区
无论是读还是写,都是从缓冲区中拿。