一.文件操作
读文件的顺序:
1.先打开文件
2.读写文件
3.关闭文件
1.1 fopen
FILE *fopen( const char *path, const char *mode );
函数说明:
1.path就是指定打开文件的路径,可以是相对路径,也可以绝对路径。mode代表打开文件的方式 2.fopen打开成功,返回FILE的有效地址,失败返回NULL. 3.fopen返回的指针是不能自己计算的,一定是要给C语言文件操作的库函数操作的
r 以只读方式打开文件,该文件必须存在,文件必须是可读的。
r+ 以可读写方式打开文件,该文件必须存在。
rb+ 读写打开一个二进制文件,允许读写数据,文件必须存在。
rw+ 读写打开一个文本文件,允许读和写。
w 打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失。若文件不存在则建立该文件。
w+ 打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件。
a 以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。(EOF符保留)
a+ 以附加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后,即文件原先的内容会被保留。 (原来的EOF符不保留)
1.2 getc
int getc( FILE *stream );
函数说明: 1.getc的功能是一个字节一个字节的读取文件内容
2.stream代表返回的FILE有效地址
1.3 fclose
int fclose( FILE *stream );
函数说明: 函数fclose()关闭给出的文件流, 释放已关联到流的所有缓冲区. fclose()执行成功时返回0,否则返回EOF.
示例代码:
#include <stdlib.h> #include <stdio.h> #pragma warning(disable:4996) void fopenUseDemo(void); int main() { fopenUseDemo(); system("pause"); return 0; } void fopenUseDemo(void) { // p 这个指针一般不用来计算,主要的用处是给C语言库函数作为参数 // 1.打开文件 FILE *p = fopen("E:\CrackCaptcha.log","r"); if (p == NULL) { printf("文件打开失败 "); }else { //printf("文件打开成功 "); //char c = getc(p); //printf("%c ",c); // 输出2 //char d = getc(p); // 第二次调用getc的时候,getc会自动从第二个BYTE开始读取文件的内容,这个是不需要我们通过代码干预的。 //printf("%c ", d);// 输出0 // 2.读取文件内容 char c = 0; while (c != EOF) // 只要不是文件结尾,那么就一直循环 { c = getc(p); printf("%c",c); } // 3.关闭文件 fclose(p); // p代表fopen成功返回的值 } }
输出结果:
1.4 putc
int fputc( int ch, FILE *stream );
函数说明: 1.第一个参数是要写入的char 2.第二个参数是fopen返回的指针
示例代码:
#include <stdlib.h> #include <stdio.h> #include <string.h> void fopenUseDemo1(void); void fopenUseDemo2(void); // int fputc( int ch, FILE *stream ); // 第一个参数是要写入的char // 第二个参数是fopen返回的指针 void fopenUseDemo1(void) { FILE *p = fopen("E:\xp.chen.txt","w"); if (p) { printf("执行成功 "); char a[100] = "hello world"; int len = strlen(a); for (int i = 0; i < len; i++) putc(a[i],p); fclose(p); } } // 实现简单的文件拷贝 void fopenUseDemo2(void) { FILE *p1 = fopen("E:\xp.chen.txt","r"); FILE *p2 = fopen("E:\naruto.txt","w"); if (p1&&p2) { // 读取p1,将读取到的内容写入p2,就实现了文件的拷贝 char c = 0; while (1) { char c = getc(p1); // 从p1中读一个字节 if (c == EOF) break; putc(c,p2); // 将p1中读到的字节写到p2 } fclose(p1); fclose(p2); } }
1.5 fgets
char *fgets( char *str, int num, FILE *stream ); 函数说明: 1.第一个参数代表待存储的字符串,第二个参数代表待存储的字符串的长度,第三个参数代表打开的文件路径
示例Demo:
#include <stdlib.h> #include <stdio.h> #include <string.h> void fgetsUseDemo(void); void fgetsUseDemo(void) { FILE *p = fopen("E:\naruto.txt","r"); if (p) { //char a[100] = {0}; //fgets(a, sizeof(a), p);//从p中读一行,包括行尾的回车 //printf("%s ",a); // 示例1:循环读取文件内容 //while (1) //{ // char a[100] = {0}; // fgets(a,sizeof(a),p); // 从p中读一行,包括行尾的回车 // if (feof(p)) // 如果p已经到了文件最后,feof返回true // break; // printf("%s",a); //} char a[100] = {0}; fgets(a,sizeof(a),p); printf("%s",a); // 示例2:循环读取所有文件内容 while (!feof(p)) { char a[100] = {0}; fgets(a,sizeof(a),p); printf("%s",a); } fclose(p); } }
int feof( FILE *stream );
注意:
1.如果文件已经到达文件结尾,feof()函数返回true 2.传入的参数是fopen返回的文件指针
1.6 fputs
int fputs( const char *str, FILE *stream ); 函数说明: 1. 第一个参数代表需要写入的内容,第二个参数代表将要写入的文件
#include <stdlib.h> #include <stdio.h> #include <string.h> void fputsUseDmeo(void); void fputsUseDmeo(void) { FILE *p = fopen("E:\xp.chen.txt","w"); if (p) { char a[100] = "仙法!超大玉螺旋手里剑"; fputs(a,p); } }
1.7 fprintf()
int fprintf( FILE *stream, const char *format, ... ); 函数说明 1.用法和printf一样,只是多了第一个参数,该参数代表打开的文件指针
// int fprintf( FILE *stream, const char *format, ... ); void fprintfUseDemo(void) { FILE *p = fopen("E:\temp.txt","w"); char a[100] = "hello"; fprintf(p,"%s",a); // 用法和printf一样,只是多了第一个参数,参数是打开的文件指针 int a1 = 4; int a2 = 5; /*sprintf(a,"%d%d",a1,a2); fputs(a,p);*/ fprintf(p,"%d,%d",a1,a2); fclose(p); }
1.8 fscanf
int fscanf( FILE *stream, const char *format, ... ); 函数说明: 1.第一个参数代表打开的文件指针 2.第二个参数代表匹配的文本 3.第三个参数代表需要赋值的变量指针。
示例代码:
假设E盘下有有一文本文件为xp.chen.txt,内容为:
则可通过fscanf来计算以上两个表达式的和
void fscanfUseDemo1(void) { FILE *p = fopen("E:\xp.chen.txt","r"); int a1, a2; fscanf(p,"%d+%d",&a1,&a2); //printf("a1=%d, a2=%d ",a1,a2); printf("%d ",a1+a2); // 计算当前两个数的和 fscanf(p, "%d+%d", &a1, &a2); //printf("a1=%d, a2=%d ", a1, a2); printf("%d ",a1+a2); fclose(p); }
1.9 stat()
int stat(const char * _Filename, struct stat * _Stat) 函数说明 1.该函数用于获取当前文件的状态 2.第一个参数代表当前文件的完整路径,第二个参数代表包含当前文件状态的结构体指针。
示例代码:
void statFuntionUseDemio(void) { struct stat fileStates = {0}; struct stat *p = &fileStates; const char *filePath = "E:\xp.chen.txt"; stat(filePath,p); _off_t fileSize = fileStates.st_size; // _off_t其实就是long类型 printf("当前这个文件的大小为:%ld ",fileSize); }
输出结果:
同时通过该函数可以获取文件的其它状态信息(文件大小,最后一次修改时间,文件属性...)
1.10 fwrite()
int fwrite( const void *buffer, size_t size, size_t count, FILE *stream ); 函数说明 1.该函数用于写二进制数据到文件 2.第一个参数代表待写数据的内存地址 3.第二个参数代表写多少个单位 4.第三个参数代表每个单位的大小 5.第四个参数是fopen返回的文件指针。
示例代码:
void fwriteUseDemo1(void) { int array[10] = {1,2,3,4,5,6,7,8,9,10}; FILE *file = fopen("E:\xp.chen.data","wb"); fwrite(array,1,sizeof(array),file); fclose(file); }
1.11 fread()
int fread( void *buffer, size_t size, size_t num, FILE *stream ); 函数说明 该函数用于读取二进制文件 1.第一个参数代表将要读入的buffer 2.第二个参数代表读多少个单位 3.第三个参数代表每个单位的大小 4.第四个参数代表待读取文件的路径。
示例Demo1:
// 读取二进制文件内容 void freadUseDemo(void) { FILE *p = fopen("E:\xp.chen.data","rb"); while (!feof(p)) { int a; int rec = fread(&a,sizeof(a),1,p); // 一个单位是1个字节,fread的返回值代表读取了多少个单位,而不是字节 //printf("%d ",a); printf("rec=%d,a=%d ",rec,a); } fclose(p); }
输出结果:
示例Demo2:
void freadUseDemo1(void) { FILE *p = fopen("E:\xp.chen.data","rb"); while (1) { int a; if (fread(&a, 1, sizeof(a), p) == 0) // 当读取的单位数为0的时候结束读取 break; printf("a = %d ",a); } }
输出结果:
示例Demo3:
// 实现文件拷贝 void freadUseDemo2(void) { FILE *p1 = fopen("E:\loginsdk.jar","rb"); FILE *p2 = fopen("E:\xxx.jar","wb"); if (p1 == NULL) return; if (p2 == NULL) return; while (1) { int a; int rc = fread(&a,1,sizeof(a),p1); // rc可以认为是从p1中读取到字节数 if (rc == 0) break; fwrite(&a, 1, rc, p2); } fclose(p1); fclose(p2); }
1.12 fseek()和ftell()
int fseek( FILE *stream, long offset, int origin ); 函数说明 1.第一个参数代表fopen打开的文件路径 2.第二个参数代表位移 3.第三个参数代表从什么地方开始
ftell()
long ftell( FILE *stream ); 函数说明 1.ftell的功能可以知道指针当前在文件的什么地方
示例代码:
// int fseek( FILE *stream, long offset, int origin ); // 第一个参数代表fopen返回的文件指针 // 第二个参数代表位移 // 第三个参数代表从什么开始 void fseekUseDemo(void) { /*char a[10] = {1,2,3,4,5,6,7,8,9,10}; FILE *p = fopen("E:\xp.chen.dat","wb"); fwrite(&a,1,sizeof(a),p); fclose(p);*/ char a[2]; FILE *p = fopen("E:\xp.chen.dat", "rb"); // 第一次打开文件的时候,指针位于文件的开始位置 //fseek(p,0,SEEK_SET);// 代表回到起始位置 // fseek(p,-4,SEEK_END); 代表从最后往前移动4个字节 fseek(p,0,SEEK_END); // 回到最后位置 fseek(p,2,SEEK_SET); // SEEK_SET代表文件开始,这句话的意思就是从文件开始向后移动两个字节 fread(&a,1,sizeof(a),p); // 所有的C语言文件读写库函数都会自动维护fopen返回的文件指针 printf("%d,%d ",a[0],a[1]); printf("ftell = %ld ",ftell(p)); // ftell的功能可以知道指针当前在文件的什么地方 // 通过下列方式可以计算出文件大小 // fseek(p,0,SEEK_END); // 先使用SEEK_END将指针移动到文件最后 // ftell(p);//然后使用ftell获得最后的偏移字节数,也就是文件的大小 fclose(p); }
运行结果:
1.13 fflush()
int fflush( FILE *stream ); 函数说明 1.fflush函数可以将缓冲区中任何未写入的数据立刻写入文件中
示例代码:
// 由于fflush是实时将缓冲区的内容写入到磁盘,所有不要大量的使用,但 // 如果是特别敏感的数据,可以通过fflush写入磁盘,防止由于电脑各种故障, // 内存数据丢失 void fflushFunctionUseDemo(void) { FILE *p = fopen("E:\xp.chen.txt","w"); while (1) { char a[100] = {0}; scanf("%s",a); if (strcmp(a, "exit") == 0) break; fputs(a,p); putc(' ',p); fflush(p); // fflush函数可以将缓冲区中任何未写入的数据立刻写入文件中 } fclose(p); }
运行结果:
1.14 remove()和rename()
void remove( const TYPE &val ); 函数说明: 删除文件,参数为文件路径
rename()
int rename( const char *oldfname, const char *newfname ); 函数说明: 函数rename()更改文件oldfname的名称为newfname. rename()成功时返回0,错误时返回非零.
示例代码:
void removeFunctionUseDemo(void) { //remove("E:\xp.chen.txt"); // 删除指定文件 rename("E:\xxx.jar","E:\nimabi.jar"); }
二.二进制和文本模式的区别
1.在windows系统中,文本模式下,文件以" "代表换行。若以文本模式打开文件,并用fputs等函数写入换行符" "时,函数会自动在" "前面加上" "。即实际写入文件的是" " 。
2.在类Unix/Linux系统中文本模式下,文件以" "代表换行。所以Linux系统中在文本模式和二进制模式下并无区别。
3.在windows下,读写文本文件的时候,是不写b的,但读写二进制文件的时候一定要写b,Linux,b是忽略的。