文章时效性提示
本文发布于 503 天前,部分信息可能已经改变,请注意甄别。
文件类型
数据文件分为文本文件和二进制文件。
数据在内存中以二进制的形式存储,如果不加以转换的输出到外存,就是二进制文件。
以ASCII字符的形式存储的文件就是文本文件。
1 2 3 4 5 6 7 8 9
| #include <stdio.h> int main() { int a = 10000; FILE* pf = fopen("test.txt", "wb"); fwrite(&a, 4, 1, pf); fclose(pf); pf = NULL; return 0; }
|
文件指针
一般通过FILE的指针来维护这个FILE结构的变量。
文件指针变量:FILE* pf
文件打开关闭
文件在读写之前先打开文件,在使用结束之后关闭文件。
在编写程序时,在打开文件的同时,会返回一个FILE*类型的指针变量指向该文件。
用fopen打开文件,用fclose关闭文件。
FILE* fopen (const char *filename, const char* mode);
int fclose (FILE* stream);
文件打开方式:
| 文件使用方式 | 含义 | 如果指定文件不存在 |
|---|
| “r”(只读) | 为了输入文件,打开一个已经存在的文本文件 | 出错 |
| “w”(只写) | 为了输出数据,打开一个文本文件 | 建立新文件 |
| “a”(追加) | 向文本末尾添加数据 | 出错 |
| “rb”(只读) | 为了输入数据,打开一个二进制文件 | 出错 |
| “wb”(只写) | 为了输出数据,打开一个二进制文件 | 建立新文件 |
| “ab”(追加) | 向一个二进制文件尾添加数据 | 出错 |
| “r+”(读写) | 为了读和写,打开一个文本文件 | 出错 |
| “w+”(读写) | 为了读和写,建立一个新文件 | 建立新文件 |
| “a+”(读写) | 打开一个文件,在文件尾读写 | 建立新文件 |
| “rb+”(读写) | 为了读和写,打开一个二进制文件 | 出错 |
| “wb+”(读写) | 为了读和写,新建一个二进制文件 | 建立新文件 |
| “ab+”(读写) | 打开一个二进制文件,在文件尾进行读写 | 建立新文件 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #include <stdio.h> #include <string.h> #include <errno.h> int main() { FILE* pf = fopen("test.txt", "w"); if (pf == NULL) { printf("%s\n",strerror(errno)); return 0; } fclose(pf); pf = NULL; return 0; }
|
文件的顺序读写
| 功能 | 函数名 | 适用于 |
|---|
| 字符输入函数 | fgetc | 所有输入流 |
| 字符输出函数 | fputc | 所有输出流 |
| 文本行输入函数 | fgets | 所有输入流 |
| 文本行输出函数 | fputs | 所有输出流 |
| 格式化输入函数 | fscanf | 所有输入流 |
| 格式化输出函数 | fprintf | 所有输出流 |
| 二进制输入 | fread | 文件 |
| 二进制输出 | fwrite | 文件 |
fputc
字符输出。
int fputc ( int character, FILE * stream );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #include <stdio.h> #include <string.h> #include <errno.h> int main() { FILE* pfWrite = fopen("test.txt", "w"); if (pfWrite == NULL) { printf("%s\n",strerror(errno)); return 0; } fputc('H', pfWrite); fputc('e', pfWrite); fputc('l', pfWrite); fputc('l', pfWrite); fputc('o', pfWrite); fclose(pfWrite); pfWrite = NULL; return 0; }
|
程序运行后,test.txt内容改为Hello。先前的内容被抹去。
fputc一次会写入一个字符。
fgetc
字符输入。
int fgetc ( FILE * stream );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #include <stdio.h> #include <string.h> #include <errno.h> int main() { FILE* pfRead = fopen("test.txt", "r"); if (pfRead == NULL) { printf("%s\n",strerror(errno)); return 0; } printf("%c",fgetc(pfRead)); printf("%c",fgetc(pfRead)); printf("%c",fgetc(pfRead)); printf("%c",fgetc(pfRead)); printf("%c",fgetc(pfRead)); fclose(pfRead); pfRead = NULL; return 0; }
|
fgetc一次读一个字符。
test.txt的内容是:Hello
fgets
文本行输入。
char * fgets ( char * str, int num, FILE * stream );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| #include <stdio.h> #include <string.h> #include <errno.h> int main() { char buf[1024] = {1}; FILE* pf = fopen("test.txt", "r"); if (pf == NULL) { printf("%s\n",strerror(errno)); return 0; } fgets(buf,1024,pf); printf("%s",buf); fgets(buf,1024,pf); printf("%s",buf); fclose(pf); pf = NULL; return 0; }
|
text.txt原先的内容是:
一个fgets会读取一行文本至最后,fgets会读取到最后的换行符,所以打印时不用加\n就会换行,加了\n就换两行。
想要读取两行文本,就用两个fgets。
fputs
文本行输出。
int fputs(const char *string,FILE *stream);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #include <stdio.h> #include <string.h> #include <errno.h> int main() { char buf[1024] = {0}; FILE* pf = fopen("test.txt", "w"); if (pf == NULL) { printf("%s\n",strerror(errno)); return 0; } fputs("hello\n", pf); fputs("world", pf); fclose(pf); pf = NULL; return 0; }
|
运行程序后,test.txt的内容为:
使用fputs函数,想在文件中换行需要自己输入\n。
1 2 3 4 5 6 7 8 9 10
| #include <stdio.h> #include <string.h> #include <errno.h> int main() { char buf[1024] = {0}; fgets(buf,1024,stdin); fputs(buf, stdout); return 0; }
|
fscanf
格式化的输入数据。
int fscnaf(FILE *stream,const char *format[,arguments]...);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #include <stdio.h> #include <string.h> #include <errno.h> struct S { int n; float f; char arr[10]; }; int main() { struct S s = {0}; FILE* pf = fopen("test.txt", "r"); if (pf == NULL) { return 0; } fscanf(pf, "%d %f %s",&(s.n),&(s.f),&(s.arr)); printf("%d %f %s\n",s.n,s.f,s.arr); fclose(pf); pf = NULL; return 0; }
|
test.txt的内容是:100 3.140000 Hello
程序运行后,屏幕上输出:100 3.140000 Hello
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| #include <stdio.h> #include <string.h> #include <errno.h> struct S { int n; float f; char arr[10]; }; int main() { struct S s ={ 0 }; fscanf(stdin, "%d %f %s",&(s.n),&(s.f),&(s.arr)); fprintf(stdout, "%d %f %s",s.n,s.f,s.arr); }
|
fprintf
以格式化的形式写文件。
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
| #include <stdio.h> #include <string.h> #include <errno.h> struct S { int n; float f; char arr[10]; }; int main() { struct S s = {100,3.14,"Hello"}; FILE* pf = fopen("test.txt", "w"); if (pf == NULL) { return 0; } fprintf(pf, "%d %f %s",s.n,s.f,s.arr); fclose(pf); pf = NULL; return 0; }
|
程序运行后,test.txt被改为:100 3.140000 Hello
fread
以二进制的形式读文件。
size_t fread ( void * ptr, size_t size, size_t count, 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
| #include <stdio.h> #include <string.h> #include <errno.h> struct S { char name[20]; int age; double score; }; int main() { struct S s ={ 0 }; FILE* pf = fopen("test.txt", "rb"); if (pf == NULL) { return 0; } fread(&s, sizeof(struct S), 1, pf); printf("%s %d %lf\n",s.name,s.age,s.score); fclose(pf); pf = NULL; return 0; }
|
test.txt的内容为张三 12 111.999000
输出的结果是张三 12 111.999000
fwirte
以二进制的形式写文件。
size_t fwrite ( const void * ptr, size_t size, size_t count, 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
| #include <stdio.h> #include <string.h> #include <errno.h> struct S { char name[20]; int age; double score; }; int main() { struct S s = {"张三",12,111.999}; FILE* pf = fopen("test.txt", "w"); if (pf == NULL) { return 0; } fwrite(&s, sizeof(struct S), 1, pf); fclose(pf); pf = NULL; return 0; }
|
程序运行后,test.txt的内容被改为张三 12 111.999000
文件的随机读写
fseek
根据文件指针的位置和偏移量来定位文件指针。
int fseek (FILE* stream , long int offset , int origin );
long int offset是偏移量,int origin是文件指针的当前位置。
test.txt文件的内容是abcdef
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| #include <stdio.h> #include <string.h> #include <errno.h> int main() { FILE* pf = fopen("test.txt", "r"); if (pf == NULL) { return 0; } fseek(pf, 1, SEEK_CUR); int ch = fgetc(pf); printf("%c\n",ch); fclose(pf); pf = NULL; }
|
ftell
返回文件指针相对于起始位置的偏移量。
long int ftell (FILE *stream);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #include <stdio.h> #include <string.h> #include <errno.h> int main() { FILE* pf = fopen("test.txt", "r"); if (pf == NULL) { return 0; } fgetc(pf); int pos = ftell(pf); printf("%d\n",pos); fclose(pf); pf = NULL; }
|
打印的结果是1
rewind
让文件指针位置回到文件的起始位置
void rewind (FILE* stream);
test.txt文件的内容是abcdef
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| #include <stdio.h> #include <string.h> #include <errno.h> int main() { FILE* pf = fopen("test.txt", "r"); if (pf == NULL) { return 0; } int ch = fgetc(pf); printf("%c ",ch); rewind(pf); ch = fgetc(pf); printf("%c ",ch); fclose(pf); pf = NULL; }
|
文件结束的判定
被错误使用的feof
在文件读取的过程中,不能用feof的返回值判断文件是否读取结束。
这个函数是用于当文件读取结束时,判断时读取失败结束,还是遇到文件尾结束。
test.txt文件的内容是abcdef
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
| #include <stdio.h> #include <string.h> #include <errno.h> int main() { FILE* pf = fopen("test.txt", "r"); if (pf == NULL) { perror("open file test.txt"); return 0; } int ch = 0; while ((ch = fgetc(pf)) != EOF) { putchar(ch); } if (ferror(pf)) { printf("error\n"); } else if (feof(pf)) { printf("end of file\n"); } fclose(pf); pf = NULL; }
|
打印的结果是abcdefend of file