C语言:文件处理(知识总结)

在现今与计算机密切交流中,文件作为计算机中不可或缺的一部分。而文件可用于存储程序、文档、数据、书信、表格、图形、照片、视频等等诸多信息。
在这里对于文件的相关内容做一个结合,可能存在遗留或偏差,恳请提出建议修改

一、文件函数内容

函数有以下21种功能

函数 原型 功能
fopen() FILE *fopen(const char *filename, const char *mode) 给定的模式 mode 打开 filename 所指向的文件
putc() int putc(int char, FILE *stream) 从指定的流 stream 获取下一个字符(一个无符号字符),并把位置标识符往前移动。
getc() int getc(FILE *stream) 把参数 char 指定的字符(一个无符号字符)写入到指定的流 stream 中,并把位置标识符往前移动
exit() void exit(int status) 立即终止调用进程
fclose() int fclose(FILE *stream) 关闭流 stream。刷新所有的缓冲区。
fprintf() int fprintf(FILE *stream, const char *format, ...) 发送格式化输出到流 stream 中。
fscanf() int fscanf(FILE *stream, const char *format, ...) 从流 stream 读取格式化输入。
fgets() char *fgets(char *str, int n, FILE *stream) 从指定的流 stream 读取一行,并把它存储在 str 所指向的字符串内
fputs() int fputs(const char *str, FILE *stream) 把字符串写入到指定的流 stream 中,但不包括空字符。
rewind() void rewind(FILE *stream) 设置文件位置为给定流 stream 的文件的开头。
fseek() int fseek(FILE *stream, long int offset, int whence) 设置流 stream 的文件位置为给定的偏移 offset,参数 offset 意味着从给定的 whence 位置查找的字节数。
ftell() long int ftell(FILE *stream) 返回给定流 stream 的当前文件位置。
fflush() int fflush(FILE *stream) 刷新流 stream 的输出缓冲区。
fgetpos() int fgetpos(FILE *stream, fpos_t *pos) 获取流 stream 的当前文件位置,并把它写入到 pos。
fsetpos() int fsetpos(FILE *stream, const fpos_t *pos) 设置给定流 stream 的文件位置为给定的位置。参数 pos 是由函数 fgetpos 给定的位置。
feof() int feof(FILE *stream) 测试给定流 stream 的文件结束标识符
ferror() int ferror(FILE *stream) 测试给定流 stream 的错误标识符。
ungetc() int ungetc(int char, FILE *stream) 把字符 char(一个无符号字符)推入到指定的流 stream 中,以便它是下一个被读取到的字符
setvbuf() int setvbuf(FILE *stream, char *buffer, int mode, size_t size) 定义流 stream 应如何缓冲
fread() size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) 从给定流 stream 读取数据到 ptr 所指向的数组中
fwrite() size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) 把 ptr 所指向的数组中的数据写入到给定流 stream 中

二、什么是文件

文件(file)一般指的是磁盘或者固态硬盘上一段已近命名的存储区。对于C而言,stdio.h的头文件就是一个文件的名称,该文件包含着些许有用的信息。对于操作系统而言,文件可能更加复杂。
例如:大型文件会被分开存储,或者包含额外的一些信息/数据,方便操作系统确定的文件。
不过,在这而言,我们更加关注的是C程序如何处理好文件。
在C中,文件是一系列连续的字节,每个字节都被单独读取。着与UNIX环境里结构相对应。
在C中会提供两种文件格式:文本模式二进制模式

三、文本模式/二进制模式

  1. Windows系统,文本模式下,文件以"“代表换行。若以文本模式打开文件,并用fputs等函数写入换行符”\n"时,函数会自动在"\n"前面加上"\r",实际写入文件的是""
  2. Unix/Linux系统,文本模式下,文件以"\n"代表换行,即Linux系统中在文本模式与二进制模式无区别。

四、标准文件

在C程序中将会自动打开3个文件,标准输入(standard input)、标准输出(standard output)与标准错误输出(standard error output)。
默认情况:标准的输入基于普通的输入设备,通常为键盘。标准输出和标准错误输出指的是系统的普通输出设备,通常为显示屏。

五、标准I/O

与标准环境的底层I/O相比,标准的I/O除了具有可移植外还有两大好处

  1. 标准I/O简化了许多专门的函数问题
  2. 输入和输出都有缓冲。

1.fopen()简述

任何程序/文件如需要使用则需要打开,在C中打开文件需要通过函数fopen()函数打开,该函数声明在stdio.h文件中。其语法如上所示。
其中:mode各自作用如下表所示

模式字符串含义
"r"以只读的模式打开文件
"w"以写的方式打开文件,把现有的文件长度截为0,如果文件不存在,则新建一个文件
"a"以写的模式打开,在现有文件末尾添加内容,如果文件不存在,则新建一个文件
"r+"以更新的模式打开文件(即可以读写文件)
"a+"以更新模式打开文件(读写文件),在现有文件末尾添加内容,如果文件不存在则新建一个文件;可以读取整个文件,但是只能在末尾添加内容
"rb"、"wb"、"ab"、"rb+"、"r+b"、"wb+"、"w+b"、"ab+"、"a+b"与上一模式类似,但是是以二进制的方式打开文件
"wx"、"wbx"、"w+x"、"wb+x"或"w+bx" C11,如果文件已存在或者以独占的形式打开文件,则打开文件夹失败
备注:犹如UNIX 和 Linux这样只有一个文件类型的系统,带b字母的模式和不带b字母的模式一致 在C11模式新增x字母的写模式。
警告:
如果使用任何一种“w”(不带x字母)模式打开现有的文件,均会将原有文件删除!!!
如带x字母的任何一种模式,则无法打开一个现有文件!

代码演示:

#include<stdio.h>
int main(int argc,char* argv[]){
	FILE *fp;
	fp = fopen("新建文件名.txt","w");//以新建文件的形式打开文件!
	fclose(fp);//关闭文件
	return 0;
}

2.getc()和putc()函数

getc()和putc()函数与getchar()和putchar()函数类似。但是不同的是,我们需要告诉getc()和putc()使用哪一个文件。
其中:
ch = getchar();//从标准输入中获取一个字符
ch = getc(fp);//从fp指定文件里读取一个字符
类似的:
putc(ch,fpout);//吧字符ch放入FILE指针fpout指定的文件里

代码演示:

#include <stdio.h>
int main (){
   FILE *fp;
   int ch;
   fp = fopen("file.txt", "w");
   for( ch = 65 ; ch <= 90; ch++ ) //写入大写字母到文件里,以新建的格式
   {
      putc(ch, fp);
   }
   fclose(fp);
   return(0);
}

3.文件结尾

我们在读取数据的程序在读到文件结尾时需要停止,这里我们就需要告诉程序已经读取完毕需要停止,但是我们如何停止呢?
如果getc()函数在读取一个字符时,发现是文件结尾,它将返回一个特殊值EOF。这里我们通过添加条件语句判断是否截止,当然,我们需要判断的是是否为空文件。

4.fclose()函数

上面两个代码演示中,我们看到了fclose()函数,但是具体是什么意思呢?
fclose(fp)函数关闭fp指定的文件,必要时刷新缓冲区。而对于比较正式的程序,我们应该检测时候成功关闭文件,如成功关闭返0,失败EOF;

if(fclose(fp) != 0){
	printf("Error in closing file %s\n",argv[1]);
}

如出现磁盘已满,移动硬盘移除或I/0错误,则调用fclose()函数失败。

5.文件I/0:fprintf()、fscanf()、fgets()、fputs()

文件I/O流处理函数中,FILE指针指向特定文件与getc()、putc()类似。

5.1fprintf()和fscanf()函数

文件I/O函数fprintf()和fscanf()函数的工作方式与printf()和scanf()类似。
代码演示:

  1. fprintf()函数:
#include<stdio.h>
#include <stdlib.h>
int main(){
	FILE *fp;
	fp = fopen("file.txt","w+");
	fprintf(fp,"%s %s %d","Hello","World!",2022);//向文件写入三个值,分别为Hello World! 2022
	fclose(fp);
	return 0;
}
  1. fscanf()函数:
#include <stdio.h>
#include <stdlib.h>
int main(){
   char str1[10], str2[10], str3[10];
   int year;
   FILE * fp;

   fp = fopen ("file.txt", "w+");
   fputs("We are in 2014", fp);
   rewind(fp);
   fscanf(fp, "%s %s %s %d", str1, str2, str3, &year); 
   printf("Read String1 |%s|\n", str1 );
   printf("Read String2 |%s|\n", str2 );
   printf("Read String3 |%s|\n", str3 );
   printf("Read Integer |%d|\n", year );
   fclose(fp);
   return(0);
}
5.2fgets()和fputs()函数

fgets()函数与gets()函数一样,表示存储输入位值的地址(char *类型),第二个参数表示字符串大小,最后一个参数表示文件指针,指定带读取的文件。

	fgets(buf,stlen,fp);

fputs()函数接受两个参数,第一个是字符串地址;第二个是文件指针。

	fputs(buf,fp);

这里buf是字符串地址,fp为目标文件
代码演示:
fputs()函数

#include <stdio.h>
int main (){
   FILE *fp;

   fp = fopen("file.txt", "w+");

   fputs("你好,", fp);
   fputs("世界!", fp);

   fclose(fp);
   
   return(0);
}

fgets()函数

#include <stdio.h>
#include <stdlib.h>
int main()
{
   FILE *fp;
   char str[60];
   /* 打开用于读取的文件 */
   fp = fopen("file.txt" , "r");
   if(fp == NULL) {
      perror("打开文件时发生错误");
      exit(0);
   }
   if( fgets (str, 60, fp)!=NULL ) {
      /* 向标准输出 stdout 写入内容 */
      puts(str);
   }
   fclose(fp);
   
   return(0);
}
5.3 随机访问:fseek()和ftell()

有了fseek()函数,便可吧文件看做是数组,在fopen()打开的文件直接移动到任意节点处。

fseek()函数声明:
int fseek(FILE *stream, long int offset, int whence)

参数
stream – 这是指向 FILE 对象的指针,该 FILE 对象标识了流。
offset – 这是相对 whence 的偏移量,以字节为单位。
whence – 这是表示开始添加偏移 offset 的位置。它一般指定为下列常量之一:

常量描述
SEEK_SET文件的开头
SEEK_CUR文件指针的当前位置
SEEK_END文件的末尾
ftell()函数声明:
long int ftell(FILE *stream)

参数
stream – 这是指向 FILE 对象的指针,该 FILE 对象标识了流。
代码演示:
fseek()

#include <stdio.h>

int main (){
   FILE *fp;

   fp = fopen("file.txt","w+");
   fputs("Hello World!", fp);
  
   fseek( fp, 6, SEEK_SET );
   fputs("C primer plus!", fp);
   fclose(fp);
   
   return(0);
}

ftell()

#include <stdio.h>

int main ()
{
   FILE *fp;
   int len;

   fp = fopen("file.txt", "r");
   if( fp == NULL ) 
   {
      perror ("打开文件错误");
      return(-1);
   }
   fseek(fp, 0, SEEK_END);

   len = ftell(fp);
   fclose(fp);

   printf("file.txt 的总大小 = %d 字节\n", len);
   
   return(0);
}
5.4 fread()和fwrite()

介绍着两者之前,首先了解相关背景知识!之前所用到的I/O函数都是面向文本的,用于处理字符和字符串。如何在文本中保存数值数据?这里就需要这两者函数实现!

fwrite()函数

关乎size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
参数

ptr -- 这是指向要被写入的元素数组的指针。
size -- 这是要被写入的每个元素的大小,以字节为单位。
nmemb -- 这是元素的个数,每个元素的大小为 size 字节。
stream -- 这是指向 FILE 对象的指针,该 FILE 对象指定了一个输出流。

例如:

char buffer[256];
fwrite(buffer,256,1,fp);

上面调用一块256字节的数据从buffer写入文件。
特别的,要保存一块10个double类型值得数组,我们可以

	double str[10];
	fwritr(str,sizeof(double),10,fp);
size_t fread()函数

关乎size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
参数

ptr -- 这是指向带有最小尺寸 size*nmemb 字节的内存块的指针。
size -- 这是要读取的每个元素的大小,以字节为单位。
nmemb -- 这是元素的个数,每个元素的大小为 size 字节。
stream -- 这是指向 FILE 对象的指针,该 FILE 对象指定了一个输入流。

例如:我们要恢复保存的内含10个double类型的数组,可以这样

double str[10];
fread(str,sizeof(double),10,fp);

该调用吧10个double大小的值拷贝到str数组中
fread()函数放回成功读取项的数量。正常放回的是nmemb,如出现错误,则放回比nmemb小。

以上是部分文件知识总结,可能存在这部分的知识漏缺,望请私信进行修正。
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不知名的MasaNvi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值