当前位置:   article > 正文

C语言:关于文件的相关操作函数总结_c语言文件操作函数总结

c语言文件操作函数总结

1.文本文件与二进制文件的操作

文本文件就是把每一个字符的ASCII码存放到文件中

二进制文件就是把数据对应的二进制形式存储到文件中

1.1打开文件:

FILE* fopen(const char* filename,const char* mode);

(1)函数参数:

    filename:文件名

    mode:文件打开的权限,权限包括如下:

模式含义
“r”只读
“w”只写
“a”文件末尾只写
“r+”在读的基础上增加可写的功能
“w+”向文件中写入数据,然后可读取文件的内容
“a+”文件末尾只写,并且可以读
“rb”二进制只读
“wb”二进制只写
“ab”二进制文件尾只写
“rb+”二进制文件在读的基础上增加可写的功能
“wb+”向二进制文件中写入数据,然后可读取文件的内容
“ab+”

二进制文件末尾只写,并且可以读

(2)返回值:

    打开成功返回FILE类型的指针,打开失败返回NULL

1.2关闭函数:

int fclose(FILE* stream)

(1)函数参数:

    stream:指向需要关闭流的指针

(2)返回值:

    关闭成功返回0,关闭失败返回-1 

1.3字符串格式化函数:

int sprintf(char*  str,const char* format,……)

(1)函数参数:

    str:指向缓冲区的指针,是将format里面的格式化字符串写入此缓冲区

    format:格式化字符串,同printf的格式规范相同

    ……:附加参数

(2)返回值:

    成功返回写入的字符总数,失败返回负数

(3)示例:

  1. #include<stdio.h>
  2. int main()
  3. {
  4. char buff[128];
  5. int val=100;
  6. sprintf(buff,"val = %d\n",val);//此时会将字符串"val = 100\n\0"写入buff数组中,一共占11字节
  7. return 0
  8. }

1.4文本文件的读写

1.4.1格式化写入函数:

int fprintf(FILE*  stream,const char* format,……)

(1)函数参数:

    stream:将format里面的格式化字符串写入到stream流中

    format:格式化字符串

    ……:附加参数

(2)返回值:

    成功返回写入的字符总数,失败返回负数

(3)示例:

  1. #include<stdio.h>
  2. int main()
  3. {
  4. int ar[]={12,23,34};
  5. int n=sizeof(ar)/sizeof(ar[0]);
  6. FILE* fd=open("text.txt","w");
  7. if(fd==nullptr)
  8. {
  9. printf("打开文件失败");
  10. exit(EXIT_FAILURE);
  11. }
  12. for(int i=0;i<n;++i)
  13. {
  14. fprntf(fd,"%d",ar[i]);//将ar数组里面的元素转为字符存储到fd这个文件描述符所指向的text.ext文本文件中
  15. }
  16. close(fd);
  17. fd=nullptr;
  18. return 0;
  19. }

1.4.2从流中读取格式化数据函数

int fscanf(FILE* stream,const char* format,……)

(1)函数参数:

    stream:从stream这个流中读取数据

    format:格式化字符串,遵循scanf的格式规范

    ……:附加参数

(2)返回值

    成功返回接收参数的数量,失败返回-1

(3)示例:

  1. #include <stdio.h>
  2. #define SIZE 10
  3. int main()
  4. {
  5. FILE* fd=fopen("text.txt","r");
  6. if(fd==nullptr)
  7. {
  8. printf("打开文件失败");
  9. exit(EXIT_FAILURE);
  10. }
  11. const int n=10;
  12. int br[n]={0};
  13. for(int i=0;i<n;++i)
  14. {
  15. fscanf(fd,"%d",&br[i]);//从fd这个文件描述符所指的ext.txt文件中读出数据,以"%d"这种数字的格式存储到br数组中
  16. }
  17. fclose(fd);
  18. fd=nullptr;
  19. return 0;
  20. }

1.5二进制文件的读写

1.5.1二进制文件的写入函数

size_t fwrite(const void* ptr,size_t size,size_t count,FILE* stream);

(1)函数参数:

    prt:从ptr指向的地址获取内容从而写入到stream这个流中

    size:单位元素的大小

    count:总共的元素数

    stream:指向被写入的流

(2)返回值:

成功返回写入元素的个数,如果失败,返回的元素个数会小于count

(3)示例:

  1. #include <stdio.h>
  2. int main()
  3. {
  4. FILE* fdw=fopen("text,txt","wb");
  5. if(fdw==nullptr)
  6. {
  7. printf("打开文件失败");
  8. exit(EXIT_FAILURE);
  9. }
  10. int ar[]={12,23,34,45};
  11. int n=sizeof(ar)/sizeof(ar[0]);
  12. //将ar这个数组里面的所有元素以二进制的形式写入到fdw所指向的文件中
  13. fwrite(ar,sizeof(int),n,fdw);
  14. fclose(fdw);
  15. fdw=nullptr;
  16. return 0;
  17. }

1.5.2二进制文件的读出函数

size_t fread(const void* ptr,size_t size,size_t count,FILE* stream);

(1)函数参数:

    prt:从stream这个流中读取内容存放到ptr所指的地址

    size:单位元素的大小

    count:总共的元素数

    stream:需要读取内容的流

(2)返回值:

成功返回读取元素的个数,如果失败,返回的元素个数会小于count

(3)示例:

  1. #include <stdio.h>
  2. int main()
  3. {
  4. FILE* fdr=fopen("text,txt","rb");
  5. if(fdr==nullptr)
  6. {
  7. printf("打开文件失败");
  8. exit(EXIT_FAILURE);
  9. }
  10. int n=10;
  11. int ar[n]={0};
  12. //读取fdr所指向的二进制文件,读取sizeof(int)*n个字节,一次存放到ar数组中
  13. fread(ar,sizeof(int),n,fdr);
  14. fclose(fdr);
  15. fdr=nullptr;
  16. return 0;
  17. }

2.缓冲和非缓冲文件的操作

缓冲文件就是指从内存向磁盘输出数据先存放到缓冲区,装满后再放到磁盘。反向亦如此。

非缓冲文件就是直接将数据从内存输出到磁盘,中间不经过缓冲区

2.1清除读写缓冲区

int fflush(FILE* stream)

(1)函数参数:

 stream:指向输出流或者更新流,fflush函数会把任何未被写入的数据写入stream指向的文件,比如stdout。

(2)返回值:

如果成功刷新或者指定的流没有缓冲区,又或者以只读可打开文件的时候返回0

返回EOR(表示-1)则会指出一个错误

(3)常见用法:

fflush(stdin):刷新标准输入缓冲区,把标准输入缓冲区里面的数据丢弃掉(注释:并非所有编译器都支持此功能,因为C/C++的标准里面并没有定义此用法,所以使用fflush(stdin)并不是正确的方式)

fflush(stdout):刷新标准输出缓冲区,把输出缓冲区里面的东西打印到标准输出设备上

2.2把缓冲区与流相关

之所以需要把缓冲区和流相关的目的在于:使用fopen\fread\fwrite\fprintf\fscanf函数的时候,会直接在内存中操作,减少内存到磁盘IO读写的操作次数,从而提高系统利用率。比如程序设计到使用数据库、视频、音频等大量爆发式磁盘到内存的IO情况,可以使用setvbuf优化内存IO。需要注意的是:linux\windows会自动处理这些问题。

2.2.1void setbuf(FILE* stream,char* buffer)

(1)函数功能:

设置流操作的内部缓冲区,长度至少为BUFSIZE个字符,这个函数应该在打开流后,立即调用,在任何对该流做输入输出前

需要注意一下几点:

①如果buffer不为空,等价于setvbuf(stream,buffer,_IOFBF,BUFSIZE)

②如果buffer为空,则等价于setvbuf(stream,NULL,_IONBF,0)

③避免需要使用缓冲区的内容时,因为作用域的原因导致缓冲区被释放了,例如:

  1. int main()
  2. {
  3. char buff[128];
  4. setbuf(stdout,buff);
  5. int x;
  6. while(x=(getchar())!=EOF)
  7. {
  8. putchar(x);//将输入的内容先从放到buff的缓冲区中,然后等到缓冲区满再输出
  9. }
  10. }

上述程序是错误的,原因是如果缓冲区buff没有被放满,就不会输出,但是由于输入的x=-1,退出循环,程序结束,就会将buff里面的内容释放,所以无法将之前输入的内容正常输出。因此应该注意缓冲区的生存期。

(2)函数参数:

stream:要设置缓冲区的文件流

buffer:指针指向需要用到的缓冲区,如果指向NULL,表示不需要缓冲区

(3)示例:

  1. int main()
  2. {
  3. char buff[1024];
  4. FILE* fd=open("text.txt","w");
  5. int a=100,b=200;
  6. //把变量a,b通过字符串的形式先写入缓冲区buff中,然后再从缓冲区中写入到fd所指向的文件内部
  7. setbuf(fd,buff);
  8. fprintf(fd,"a = %d,b = &=%d\n",a,b);
  9. fclose(fd);
  10. fd=nullptr;
  11. return 0;
  12. }

2.2.2 int setvbuf(FILE* stream,char* buffer,int mode,size_t size);

(1)函数功能:

此函数的功能和setbuf差不多,只不过由于参数的不同,所以setvbuf可以指定缓冲区的大小

使用此函数还需要注意如下几点:

①当buffer为空,可以通过mode、size来重置内部缓冲区的大小

②当buffer不为空,可以通过mode、size来设置提供的buffer这个缓冲区的大小

③这个函数应该在打开流后,立即调用,在任何对该流做输入输出前

(2)函数参数:

stream:要设置缓冲的文件流

buffer:指向缓冲区

mode:缓冲模式

           _IOFBF:全缓冲(当缓冲区满时在想流写入数据)

           _IOLBF:行缓冲

           _IONBF:无缓冲

size:缓冲区的大小

(3)返回值:

成功返回0,失败返回非零

3.文件位置操作

3.1返回当前文件位置的指示值

long ftell(FILE* stream)

(1)参数:

stream:要检验的文件流

(2)返回值:

成功时返回文件位置指示器,失败则为-1L

3.2获取文件位置指示器

int fgetpos(FILE* stream,fpos_t *pos)

(1)函数作用:

将stream文件流的位置指针保存到pos这个位置变量中

(2)参数:

stream:要检验的文件流

pos:指向要存储文件位置指示器到fpos_t对象的指针

(3)返回值:

成功返回0

失败返回非零值

(4)示例:

  1. int main()
  2. {
  3. //打开text.txt文件,文件事先会有一定的内容
  4. FILE* fd=fopen("text,txt","w");
  5. fpos_t pos;
  6. //使用fgetpos函数取得文件指针的位置,并存到Pos中,此时pos=0
  7. fgetpos(fd,pos);
  8. printf("当前的文件指针在第%ld个字节",pos);
  9. //将文件位置偏移3,也就是指向文件的第4个字节
  10. fseek(fd,3,0);
  11. //此时pos的值为3
  12. fgetpos(fd,pos);
  13. printf("当前的文件指针在第%ld个字节",pos);
  14. fclose(fd);
  15. return 0;
  16. }

3.3将文件位置指示符移动到文件指定位置

3.3.1 int fseek(FILE* stream,long offset,int origin)

可以用fseek()和ftell()来计算文件的长度

  1. #include <stdio.h>
  2. int main()
  3. {
  4. FILE* fd=fopen("text,txt""r");
  5. fseek(fd,0,SEEK_END);//将文件描述符移动到尾部
  6. ftell(fd);//得出文件描述符的位置就是文件的大小
  7. close(fd);
  8. return 0;
  9. }

(1)函数参数:

stream:要修改的文件流

offset:相对origin所移动的字符数

origin:offset以origin为基础位置进行移动,包括:
          SEEK_SET:文件开头

          SEEK_CUR:当前位置

          SEEK_END:文件结尾

(2)返回值

成功时返回0,失败返回非0

(3)示例:

fseek(fd,100L,SEEK_SET):把fd指针移动到从文件开始位置计算往后100个字节的地方

fseek(fd,100L,SEEK_CUR):把fd指针移动到从文件当前位置计算往后100个字节的地方

fseek(fd,0L,SEEK_END):定位到文件结尾处

fseek(fd,-100L,SEEK_END):从文件结尾回退100字节

3.3.2 int fsetpos(FILE* stream,const fpos_t* pos)

(1)函数参数:

stream :要修改的文件流

pos:指向fpos_t对象的指针,用作文件位置指示器的新值

(2)函数返回值:

成功返回0,否则非零

3.4将文件位置指示器移动到文件首

void rewind(FILE* stream)

(1)函数作用:

移动文件描述符到文件的开始位置,等价于fseek(fd,0,SEEK_SET);

4.错误处理

4.1清除错误

void clearerr(FILE* stream)

(1)函数作用:

把文件结束符EOF和错误标识符从非0值变为0值

(2)函数参数:

stream:要重置错误标志的文件流

(3)示例:

  1. int main()
  2. {
  3. FILE* fd=fopen("text.txt","r");//打开一个文件,这个文件里面是有内容的
  4. //如果此文件的结尾不是EOF结尾,就会退出程序不再执行后序操作
  5. assert(feof(fd));
  6. int ch;
  7. //读到文件结尾遇到EOF就退出循环
  8. while((ch=fgetc(fd))!=EOF)
  9. {
  10. printf("%c",ch);
  11. }
  12. clearerr(fd);//将错误标志从非0变为0
  13. //如果没有设置文件结束符eof就会返回0,否则返回非0,上面将EOF设置为0,说明此文件没有课文件结束符,因此feof(fd)会返回0,执行else语句
  14. if(feof(fd))
  15. {
  16. printf("文件有结束符\n");
  17. }
  18. else
  19. {
  20. printf("文件没有结束符\n");
  21. }
  22. }

4.2检查文件结尾

int feof(FILE* stream)

(1)函数作用:

检查是否抵达文件流的结尾

(2)函数参数:

stream:要检验的文件流

(3)返回值:

如果已经到结尾返回非零值,否则返回0

4.3检查文件错误

int ferror(FILE* stream)

(1)函数作用:

检查给定文件流的错误

(2)返回值:若文件流已经出现错误则返回非零值,否则返回0

(3)示例:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main()
  4. {
  5. FILE* fd=fopen("text.txt","r");
  6. int c;//使用
  7. while((c=fgetc(fd))!=EOF)
  8. {
  9. putchar(c);
  10. }
  11. //ferror()与feof()分别用来区别不同的错误条件
  12. if(ferror(fd))
  13. {
  14. printf("读取的时候发生错误\n");
  15. }
  16. else if(feof(fd))
  17. {
  18. printf("成功读取到文件末尾\n");
  19. }
  20. fclose(fd);
  21. }

4.4显示对应当前错误的字符串到stderr

void perror(const char* s)

(1)函数作用:

用来将上一个函数发生错误的原因输出到标准设备stderr。然后会打印出:s所指向的字符串+错误原因字符串。

5.文件操作

5.1删除文件

int remove(const char* fname);

(1)函数作用:

删除fname这个文件名所对应的文件

(2)函数参数:

fname:待删除文件的名字(包含路径)

(3)返回值:
成功返回0,失败返回非0

5.2重命名文件

int rename(const char* old_filename,const char* new_filename);

更改文件的名字,前面的参数是原来名字,后面的参数是更改之后的文件名字

5.3返回指向临时文件的指针

5.3.1FILE* tmpfile(void)

(1)函数作用:

创建唯一的临时二进制文件(类型为wb+),并打开此文件

(2)返回值:

成功返回文件流,失败返回空

5.3.2char* tmpnam(char* s)

(1)函数作用:

生成唯一临时文件名

使用fopen创建临时文件,文件关闭,使用remove函数来删除该文件

(2)函数参数:

s指向一个char类型的数组,这个数组里面存放临时文件的名称,如果s为空,就会使用一个内部静态数组来存储临时名称。

(3)返回值:

成功时返回文件名字的指针,失败返回空

6.无格式输入、输出

6.1从文件流获取一个字符

int fgetc(FILE* stream)

int getc(FILE* stream)

(1)返回值:

成功时为获取的字符,失败返回EOF

(2)fegtc和getc的区别:

fgetc()是一个函数,getc()是一个宏,宏调用的时候参数不能是副作用表达式(副作用表达式:表达式执行完之后会改变其中某些变量的值,比如++i就是一个副作用表达式)

6.2从文件流中获取一个字符串

char* fgets(char* str,int count,FILE* stream)

(1)函数作用:
从stream这个指针所指向的文件中获取count-1个字符存放到str的字符数组中,成功时返回str,失败返回空指针

6.3将一个字符写入文件流

int fputc(int ch,FILE* stream)

int putc(int ch,FILE* stream)

(1)函数作用:

将字符ch写到stream文件流中。

(2)返回值:

成功时返回被写入的字符

失败返回EOF并设置stream上的错误指示器

6.4将一个字符串写入文件流

int fputs(const char* str,FILE* stream);

int fputs(const char* restrict str,FILE* restrict stream)

(1)函数作用:

将以NULL结尾的字符串str的每个字符写入到stream文件流中

(2)参数:

str:要写入的字符串

stream:输出流

(3)返回值:

成功时返回非负值,失败时返回EOF

(4)注意:

函数int puts(const char* str,FILE* stream)会将换行符附加到str字符串中输出给stream文件流中

而fputs写入的字符串并不会进行修改

6.5从stdin读取一个字符

int getchar(void)

(1)返回值:

成功时为获得的字符,失败时为EOF

6.6从stdin读取一个字符串

char* gets_s(char* str,rsize_t n)

(1)函数说明:

从stdin里面读取n-1个字符存储到str中,不存在缓冲区,然后遇到换行或者符或者文件尾,就会去掉换行符,并附加空字符。

(2)返回值:

成功时返回str指针,失败返回空指针

(3)备注:

fgets()函数不进行边界检查,从而导致此函数对缓冲区溢出攻击极度脆弱,无法安全使用,所以被弃用。

6.7将一个字符写入stdout

int putchar(int ch);

(1)返回值:

成功时返回写入的字符,失败返回EOF并设置stdout上的错误指示器

(2)说明:

putchar()函数的参数ch必须是处于0-127之间的一个十进制整数

如果整型ch超出八位变量的范围时,ch则会被强转为8位变量(取低八位)

如果整型ch为负数的时候,由于计算机存储负数是补码的方式,所以会被当做正数处理,也是取低八位

(3)示例:

  1. int main()
  2. {
  3. int res=0;
  4. for(char c='a';(c!=EOF)&&(c!='z');++c)
  5. {
  6. res=putchar(c);
  7. }
  8. if(res==EOF)
  9. {
  10. if(ferror(stdout))
  11. {
  12. fprintf(stderr,"putchar() failed\n");
  13. perror("putchar()");
  14. exit(EXIT_FAILURE);
  15. }
  16. }
  17. putchar("\n");
  18. //验证超出八位的字符输出结果是否和参数一样——答案肯定是不一样的
  19. int x=0x1070;
  20. printf("\n0x%x\n",r);
  21. x=putchar(x);
  22. printf("\n0x%x\n",r);
  23. }

6.8将一个字符串写入stdout

int puts(const char* str)

(1)函数参数

str:要写入的字符串

(2)返回值

成功返回非负值,失败返回EOF

6.9将一个字符退回文件流

int ungetc(int ch,FILE* stream);

(1)函数说明:

将ch字符放到流stream的输入缓冲区,从而能够从stream的后继读取该字符,而不会修改与流关联的外部设备。

(2)参数

ch:要推入输入流缓冲区的字符

stream:要回放字符到文件流

(3)返回值:

成功返回ch,失败返回EOF

(4)说明:

①使用fseek\fsetpos\rewind将会忽略ungetc所加入的字符

②如果调用一次ungetc之后,不读取或者不重新寻位,然后再次调用ungetc就有可能调用失败,因为回放缓冲区大小可能位1)

③如果成功调用多次ungect,读取操作以ungect的逆序取得回访的字符

④如果ch=EOF,操作失败不会影响流

⑤实践中,回放缓冲区的大小会在4K和A或者保证的最小值1之间变化

(5)示例:

  1. int main()
  2. {
  3. int res=0;
  4. char ch;
  5. printf("请输入整数:\n");
  6. while((ch=getchar())!=EOF&&isdigit(ch))
  7. {
  8. res=res*10+ch-'0';
  9. }
  10. if(ch!=EOF)
  11. {
  12. ungect(ch,stdin);//将字符ch退回到输入流
  13. }
  14. printf("%d,uninteger--%c\n",res,(char)(getchar()));
  15. return 0;
  16. }
  17. /*
  18. 请输入整数:
  19. 666x
  20. //输出:
  21. 666 uninteger--x
  22. */

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号