C语言【文件】

目录

 概念

 文件名

 文件的打开和关闭

fopen

fclose 

输入输出函数 

 fputc

fgetc

fputs

fgets 

fprintf

fscanf

fwrite

fread

三种流

scanf和sprintf

 结构体转化

​编辑

 文件的随机读写

fseek

ftell

rewind

文本文件和二进制文件

文件读取结束的判定

文件缓冲区


 概念

文件的作用:文件是存放于硬盘中的,使数据能够持久化保存。

数据文件文件的内容不一定是程序,它可以是程序运行时产生的读写数据。

有时后我们会将文件输出到磁盘上,在需要的时候再从磁盘上把数据读取到内存中使用。

 文件名

一个文件需要一个唯一的文件标识:
文件路径 + 文件名主干 + 文件后缀

例: c:\code\test.txt

 文件的打开和关闭
 

为了方便访问文件中的数据,每个被使用的文件都在内存中开辟了一个相应的文件信息区,记录文件名文件的状态、文件路径等)。这个文件信息区被存放在一个结构体变量中,通过文件指针可以访问这块区域,并对文件实施各种操作。

FILE* pf;//文件指针变量

 C语言【文件】_第1张图片

fopen

根据文件名打开打开文件,并返回一个FILE*类型的指针。

文件操作模式类型(第二个参数): 

C语言【文件】_第2张图片

注意文件路径可以是相对或绝对路径
 

fclose 

C语言【文件】_第3张图片

关闭文件,和fopen一起使用。 

输入输出函数 

C语言【文件】_第4张图片

 fputc

意为将字符写入到文件中。

返回值: 为字符的ASCII码值(非负值)。失败返回-1。

C语言【文件】_第5张图片 利用返回值写入的数据依次打印到屏幕上:

int main()
{
	//打开文件
	FILE* pf = fopen("text.txt", "w");
	if (NULL == pf)
	{
		perror("fopen");
		return 1;
	}
	//写文件
	int i = 0;
	for (i = 0; i < 26; i++)
	{
		putchar(fputc('a'+i, pf));
	}
	fclose(pf);
	pf = NULL;
	return 0;
}

fgetc

意为获取文件中的字符返回它的ascii码在使用fgetc前,要确保文件状态为 r 专注输入数据而非w专注输出数据,否则会导致读取失败。

 pf指针具有Placeholder指针可以遍历文件:

 C语言【文件】_第6张图片

int main()
{
	//打开文件
	FILE* pf = fopen("text.txt", "r");
	if (NULL == pf)
	{
		perror("fopen");
		return 1;
	}
int ch = 0;
	while ((ch = fgetc(pf)) != EOF)//意为读取文件所有内容之后返回-1(文件末尾)
	{
		printf("%c", ch);
	}
	fclose(pf);
	pf = NULL;
	return 0;
}

C语言【文件】_第7张图片

fputs

作用:将字符串写入到文件中,想达到按行写入可以主动加上\n

返回值:成功时返回非负值,失败返回-1。

C语言【文件】_第8张图片

 C语言【文件】_第9张图片

fgets 

作用:从文件中依次读取字符串,遇到\n或者读取(num-1)个数字后终止读取。也就是说它只读取num-1个数字并在num或\n后处自动补上\0

返回值:str的首地址,若失败返回NULL。

  C语言【文件】_第10张图片

fprintf

C语言【文件】_第11张图片

 从文件流中按照一定格式写数据。

 例如复杂的结构体

struct S
{
	char name[20];
	int age;
	float score;
};


C语言【文件】_第12张图片

fscanf

C语言【文件】_第13张图片

 从文件流中按照一定格式读数据。

 C语言【文件】_第14张图片

当然,你也可以用前面的文件读取函数进行读取:

char arr[20] = { 0 };
fgets(arr,20,pf);//也行
printf("%s",arr);

fwrite

对文件进行二进制写入。[适用于所有类型]

第一个参数为写入数据的地址,第二个参数为数据的大小,第三个参数为数据个数。类似于memcpy一个字节一个字节拷贝数据。

 注意读写二进制文件属性要变为 ”wb"

 C语言【文件】_第15张图片

这下知道文件中为什么会有乱码了吧~ 

fread

对文件进行二进制读取,会返回读取成功的count个数。

 C语言【文件】_第16张图片

三种流

C语言【文件】_第17张图片

而文件输入输出函数适用于所有流它们对数据的操作可以不局限于文件。也就是说可以用它们实现像scanf、printf之类函数的功能:

fprintf(stdout, "hello world");//屏幕
int a = 0;
fscanf(stdin,"%d" ,a);//键盘

scanf和sprintf

C语言【文件】_第18张图片

C语言【文件】_第19张图片

sscanf按照一定格式将字符串转换为特定格式

sprintf将其他数据类型按照指定的格式转换成字符串。【后面自动补‘\0’】

 结构体转化

将结构体转化成字符串:

C语言【文件】_第20张图片

 将字符串转化成结构体:C语言【文件】_第21张图片

 文件的随机读写

fseek

C语言【文件】_第22张图片

作用:将流里文件指针设置起始位置偏移量,按此偏移量的位置进行读写操作。

 C语言【文件】_第23张图片

SEEK_END为末尾数据的下一个位置 

	int ch = fgetc(pf);
	putchar(ch);
//a
	fseek(pf,-2,SEEK_END);//反向找
	ch = fgetc(pf);
	putchar(ch);
//e
	fseek(pf, 0, SEEK_SET);//回到起始位置
	ch = fgetc(pf);
	putchar(ch);
//a
	//查找完a后指针位置会向后增1
	fseek(pf, 3, SEEK_CUR);//b-->cde
	ch = fgetc(pf);
	putchar(ch);
//e

ftell

C语言【文件】_第24张图片

返回当前文件指针所指向的位置(偏移量)。

rewind

C语言【文件】_第25张图片

 将文件指针设置成最开始的位置。

文本文件和二进制文件

数据在内存中以二进制的形式存储,如果不加转换的输出到外存,就是 二进制文件 。(乱码)
字符一律以 ASCII 形式存储,数值型数据既可以用 ASCII 形式存储,也可以使用二进制形式存储。

C语言【文件】_第26张图片对于整数10000,以ASCII码存储为5个字节,而二进制存储只占4和字节。

文件读取结束的判定

牢记:在文件读取过程中,不能用 feof 函数的返回值直接用来判断文件的是否结束。
而是 应用于当文件读取结束的时候,判断是读取失败结束,还是遇到文件尾结束。
  • fgetc 判断是否为 EOF .
  • fgets 判断返回值是否为 NULL .
  • fread判断返回值是否小于实际要读的个数。

fgetc: 

int main(void)
{
    int c; // 注意:int,非char,要求处理EOF
    FILE* fp = fopen("test.txt", "r");
    if(!fp) {
        perror("File opening failed");
        return EXIT_FAILURE;
   }
 //fgetc 当读取失败的时候或者遇到文件结束的时候,都会返回EOF
    while ((c = fgetc(fp)) != EOF) 
   { 
       putchar(c);
   }

    if (ferror(fp))
        puts("I/O error when reading");
    else if (feof(fp))
        puts("End of file reached successfully");
    fclose(fp);
}

 二进制:

#include 
enum { SIZE = 5 };
int main(void)
{
    double a[SIZE] = {1.,2.,3.,4.,5.};
    FILE *fp = fopen("test.bin", "wb"); // 必须用二进制模式
    fwrite(a, sizeof *a, SIZE, fp); // 写 double 的数组
    fclose(fp);
    double b[SIZE];
    fp = fopen("test.bin","rb");
    size_t ret_code = fread(b, sizeof *b, SIZE, fp); // 读 double 的数组
    if(ret_code == SIZE) {
        puts("Array read successfully, contents: ");
        for(int n = 0; n < SIZE; ++n) printf("%f ", b[n]);
        putchar('\n');
   } else {
       if (feof(fp))
          printf("Error reading test.bin: unexpected end of file\n");
       else if (ferror(fp)) {
           perror("Error reading test.bin");
       }
   }
    fclose(fp);
}

文件缓冲区

所谓文件缓冲区,就是在使用文件时,系统会为每个文件分配一块缓冲区用于存放数据,当内存向磁盘中传输数据或当磁盘向内存中传输数据的时候,这些数据会一个一个被加载到缓存区上,再一齐被加载到内存或磁盘上。

C语言【文件】_第27张图片 C语言【文件】_第28张图片

作用:将缓存区中的数据输出到流里(stdout、FILE) 

#include 
#include 
int main()
{
	FILE* pf = fopen("text.txt", "w");
	if (NULL == pf)
	{
		perror("fopen");
		return 1;
	}
	int a = 10000;
	fwrite(&a, sizeof(int), 1, pf);//二进制
	printf("内容存放在缓冲区,此时打开文件无内容\n");
	Sleep(10000);//休眠10秒,数据已经在缓存区上了
	fflush(pf);//刷新缓冲区
	printf("再打开文件,内容已存在\n");
	fclose(pf);//注:fclose在关闭文件的时候,也会刷新缓冲区
	pf = NULL;
}

注:读取写入数据时遇到\n或fclose也会刷新缓冲区。 

所以在我们对文件进行操作时别忘了执行刷新缓冲区文件关闭操作!否则可能造成文件读写出错。

你可能感兴趣的:(c语言,开发语言,算法)