比如:当我们写了一个通讯录,运行起来后可以在里头 增减数据,而一旦退出程序后,其中的数据就会不在了,只 能在下次重新输入数据,这样的通讯录明显不符合我们的需求。

So当我们需要将数据做到持久化时,就需要使用文件将数据存放在电脑的硬盘上

一.什么是文件

1.1定义

磁盘上的文件是文件

C语言——文件操作_数据

在程序设计中,功能性的将文件一般分为:程序文件,数据文件

  • 程序文件:包括 源程序文件(后缀为 .c),目标文件(windoes环境后缀为 .obj),可执行文件(windoes环境后缀为 .exe
  • 数据文件:文件的内容不一定是程序,而是程序在运行时读写的数据, 比如程序运行需要从中读取数据的文件,或输出内容的文件。

1.2文件名

一个文件需要一个唯一的文件标识,以便进行识别和引用

文件名:文件路径+文件名主干+文件后缀

如:c:\code\test.txt


二.文件的打开与关闭

2.1文件指针

每个被使用的文件都会在内存中开辟出一个相应的文件信息区,其用来存放文件的相关信息(如文件名、文件状态 及 文件当前位置 等)。这些信息是保存在一个结构体变量中的,该结构体类型是由系统申明的,其名为 FILE

注意:文件和文件信息区是关联的,文件已改变则文件信息区也会发生改变

注意:

  1. FILE结构在不同的C编译器下设计和实现可能是有所差异的,但是大同小异
  2. 每当打开一个文件时,系统会根据文件的情况自动创建一个 FILE 结构的变量,并填充其中的信息。我们不用关其细节
  3. 一般可通过一个 FILE 的指针来维护这个 FILE 结构的变量


创建一个FILE*的指针变量:

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


//定义 pf 是一个指向 FILE 类型的指针变量,可以使 pf 指向某个文件的文件信息区(是一个结构体变量,可通过该文件信息区的信息就能够访问该文件。
可通过文件指针变量找到与其相关联的文件

2.2文件的打开与关闭

文件在读写前应该先用  fopen打开文件,使用结束后用  fclose关闭文件

fopen

  • 如果文件成功打开,该函数将返回指向FILE对象的指针;失败则返回空指针

C语言——文件操作_数据_02


方式

描述

"r"

打开一个已有的文本文件,只允许读取文件;如果这个文件不存在或未找到,则打开失败,报错

"w"


打开一个空文件,为文件;如果文件不存在,则会创建一个新文件;如果这个文件里有内容,该文件内容将被销毁

"a"

追加写入文件;如果文件不存在,则会创建一个新文件。

"r+"

打开一个文本文件,允许读写文件。

"w+"

创建一个文件;允许读写文件。如果文件已存在,则文件内容被销毁;如果文件不存在,则会创建一个新文件。

"a+"

在文件尾进行读写   ;如果文件不存在,则会创建一个新文件。读取会从文件的开头开始,写入则只 能是追加模式。

C语言——文件操作_#include_03


fclose

C语言——文件操作_#include_04

#include<stdio.h>
int mainn()
{
FILE* pf = fopen("test.txt","w");
if(pf == NULL)
{
perror("fopen");
return 1;
}
//开写文件
//。。。。。。。。。。。。
//关闭文件
fclose(pf);
pf = NULL;

}


三.文件的顺序读写

顺序读写函数

C语言——文件操作_#include_05

功能

函数名

适用于

字符输入函数

fgetc

所有输入流

字符输出函数

fputc

所有输出流

文本行输入函数

fgets

所有输入流

文本行输出函数

fputs

所有输出流

格式化输入函数

fscanf

所有输入流

格式化输出函数

fprintf

所有输出流

二进制输入

fread

文件

二进制输出

fwrite

文件



fputc(字符输出函数)

C语言——文件操作_输入流_06

#include <stdio.h>
int main()
{
FILE* pf = fopen("test.txt", "w");
if (pf == NULL)
{
perror("fopen");
return 1;
}
// 写文件
fputc('b', pf);
fputc('y', pf);
fputc('e', pf);

// 关闭文件
fclose(pf);
pf = NULL;

return 0;
}

运行后不会直接看见bye.

而当我们打开文本后可以看到:

C语言——文件操作_数据_07


fgetc(字符输入函数)

  • 从流中读取一个字符,位置标识符向前移动一(字符必须为一个无符号字符
  • 参数为 指向标识输入流的FILE对象的指针。
  • 如果读取成功会返回相应的ASCII码值,读取失败它会返回一个EOF

//从文件里读取

#include <stdio.h>
int main()
{
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
// 写文件
int ret = fgetc(pf);
printf("%c\n",ret);
ret = fgetc(pf);
printf("%c\n",ret);
ret = fgetc(pf);
printf("%c\n",ret);
// 关闭文件
fclose(pf);
pf = NULL;

return 0;
}


//从标准输入流 (键盘)读取

#include <stdio.h>
int main()
{
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
// 写文件
int ret = fgetc(stdin);
printf("%c\n",ret);
ret = fgetc(stdin);
printf("%c\n",ret);
ret = fgetc(stdin);
printf("%c\n",ret);
// 关闭文件
fclose(pf);
pf = NULL;

return 0;
}

C语言——文件操作_#include_08


fputs(文本行输出函数)

  • str指向流的C 字符串写入

C语言——文件操作_数据_09

#include <stdio.h> 
int main()
{
FILE* pf = fopen("test.txt", "w");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//写文件 ——按照行来写
fputs("abcdef\n", pf);
fputs("zxcvbnm\n", pf);

//关闭文件
fclose(pf);
pf = NULL;
return 0;
}

fgets(文本行输入函数)

C语言——文件操作_#include_10

  • 读取时由于最后会使用一个进行\0的读取,所以一次最多读取n-1个

#include <stdio.h>
int main()
{
char arr[10] = {0}; // 存放处
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//读文件 - 按照行来读
fgets(arr, 4, pf);
printf("%s\n", arr);
fgets(arr, 4, pf);
printf("%s\n", arr);

// 关闭文件
fclose(pf);
pf = NULL;
return 0;
}

C语言——文件操作_输入流_11


fprintf(格式化输出函数)

  • 将一个格式化的数据写到文件里
#include <stdio.h>
struct S
{
char arr[10];
int num;
float wb;
};
int main()
{
struct S s = { "qazxsw", 10, 8.2f };
// 对格式化的数据进行 写文件
FILE* pf = fopen("test.txt", "w");
if (pf == NULL)
{
perror("fopen");
return 1;
}
// 写文件
fprintf(pf, "%s %d %f", s.arr, s.num, s.wb);

// 关闭文件
fclose(pf);
pf = NULL;
return 0;
}

C语言——文件操作_输入流_12


fscanf(格式化输入函数)

C语言——文件操作_输入流_13

#include <stdio.h>

struct S
{
char arr[10];
int num;
float wb;
};
int main()
{
struct S s = { "qazxsw", 10, 8.2f };

// 对格式化的数据进行 写文件
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
// 读文件
fscanf(pf,"%s %d %f", s.arr, &(s.num), &(s.wb));

//打印
printf("%s %d %f\n", s.arr ,s.num ,s.wb) ;
// 关闭文件
fclose(pf);
pf = NULL;
return 0;
}
//qazxsw 10 8.200000


fwrite(二进制输出)

  • 写数据到流中

C语言——文件操作_数据_14

#include <stdio.h>

struct S
{
char arr[10];
int num;
float wb;
};
int main()
{
struct S s = { "qazxsw", 10, 8.2f };
//二进制形式 写
FILE* pf = fopen("test.txt", "w");
if (pf == NULL)
{
perror("fopen");
return 1;
}
// 写文件
fwrite(&s, sizeof(struct S), 1, pf) ;

// 关闭文件
fclose(pf);
pf = NULL;
return 0;
}

在记事本中打开test.txt,可以看到除了字符串,其他是乱码:

C语言——文件操作_输入流_15

得要搭配fread函数来看



fread(二进制输入)

  • 从流中读取数据到ptr

C语言——文件操作_#include_16

#include <stdio.h>

struct S
{
char arr[10];
int num;
float wb;
};
int main()
{
struct S s = { "qazxsw", 10, 8.2f };
//二进制形式 读
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
// 读文件
fread(&s, sizeof(struct S), 1, pf) ;
printf("%s %d %f",s.arr ,s.num ,s.wb) ;

// 关闭文件
fclose(pf);
pf = NULL;
return 0;
}
//qazxsw 10 8.200000

  小结:fwite写,fread读


流:

c语言程序,只要运行,就默认打开3个流(均为FILE*):

stdin——标准输入流——从键盘  输入

stdout——标准输出流——输出至  屏幕

stderr——标准错误流——输出至 屏幕

例子:使用stdout下

C语言——文件操作_#include_17

scanf,printf和fscanf,fprintf区别

scanf   针对标准输入的格式化的输入语句 —— stdin

fscanf  针对所有输入流的格式化的输入语句 —— stdin/文件

printf 针对标准输出的格式化的shuchuyuju输出语句 —— stdout

fprintf 针对所有输入流的格式化的输出语句 —— stdout/文件


四.文件的随机读写

4.1 fseek

  • 根据文件指针的位置和偏移量来定义文件指针

C语言——文件操作_#include_18

C语言——文件操作_输入流_19

  • 偏移量为负数——表示向后多少;正数——表示向前多少
#include <stdio.h>

int main(void)
{
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}

// 读取文件
int ch = fgetc(pf);
printf("%c\n", ch);

ch = fgetc(pf);
printf("%c\n", ch);

ch = fgetc(pf);
printf("%c\n", ch);

// 关闭文件
fclose(pf);
pf = NULL;

return 0;
}
//q a z

当加入fseek函数:

#include <stdio.h>

int main(void)
{
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}

// 读取文件
int ch = fgetc(pf);
printf("%c\n", ch);

fseek(pf ,-1 ,SEEK_CUR);//往后1个字节

ch = fgetc(pf);
printf("%c\n", ch);

ch = fgetc(pf);
printf("%c\n", ch);

// 关闭文件
fclose(pf);
pf = NULL;

return 0;
}
//q q a


4.2 ftell

  • 返回文件指针相对于起始位置的偏移量
#include <stdio.h>

int main(void)
{
FILE* pf = fopen("test1.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}

// 读取文件
int ch = fgetc(pf);
printf("%c\n", ch);

fseek(pf ,-2 ,SEEK_END);

ch = fgetc(pf);
printf("%c\n", ch);
ch = fgetc(pf);
printf("%c\n", ch);

int ret = ftell(pf);
printf("%d\n",ret);

// 关闭文件
fclose(pf);
pf = NULL;

return 0;
}
//a e f 6

4.3  rewind

  • 让文件指针的位置回到文件的起始位置
#include <stdio.h>

int main(void)
{
FILE* pf = fopen("test1.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}

// 读取文件
int ch = fgetc(pf);
printf("%c\n", ch);

fseek(pf ,-2 ,SEEK_END);

ch = fgetc(pf);
printf("%c\n", ch);
ch = fgetc(pf);
printf("%c\n", ch);

int ret = ftell(pf);
printf("%d\n",ret);

//让文件回到起始位置
rewind(pf);
ch = fgetc(pf);
printf("%c\n", ch);

// 关闭文件
fclose(pf);
pf = NULL;

return 0;
}
//a e f 6 a