文件操作(上)
- 1、使用文件的原因
- 2、什么是文件
- 3、二进制文件和文本文件
- 4、 流的打开与关闭
- 4.1 流和标准流
- 4.1.1 流
- 4.1.2 标准流
- 4.2 文件指针
- 4.3 文件的打开和关闭
- 5、文件的顺序读写
- 5.1 顺序读写函数介绍
- 5.1.1 fputc与fgetc
1、使用文件的原因
首先来看一个代码:
int main()
{
int a = 0;
printf("a = %d\n", a);
scanf("%d", &a);
printf("a = %d\n", a);
return 0;
}
当我们输入一个100,代码的运行结果是:
可以看到,a变成了100,那么我们关闭程序,再次运行程序a还会是100吗?
a又变为0,这是为什么呢?
原因是: a是在内存上的一块空间,如果程序退出,内存会归还给操作系统,a中的数据就会丢失,所以第二次运行程序时是看不到上一次的数据的,如果我们想要持久化的保存数据,我们可以将数据保存在硬盘上的文件中。
2、什么是文件
磁盘(硬盘)上的文件就是文件
我们一般所说的文件有两种,一种是程序文件,一种是数据文件
程序文件: 源程序文件(后缀为.c),目标文件(Windows环境下的目标文件后缀为.obj),可执行程序(Windows环境下的目标文件后缀为.exe)
数据文件: 文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件,或者输出内容的文件。
文件名: 文件路径+文件名主干+文件后缀
例如:c:\code\test.txt
3、二进制文件和文本文件
根据文件的内容可以将文件划分为二进制文件和文本文件
数据是以二进制的补码存储在内存中的,如果不加转换的输出到外存的文件中去,就叫做二进制文件
如果在存储前将数据转换成ASCII值的形式存储到外存中,以ASCII码字符存储的文件就叫做文本文件
举个例子,将 10000 存储到文件中,以二进制形式输出到硬盘上占4个字节,而以ASCII值形式输出则占用5个字节
代码:
int main()
{
int a = 10000;
FILE* p = fopen("data.txt", "wb");//w是写,b是以二进制的形式
fwrite(&a, 4, 1, p);
fclose(p);
p = NULL;
return 0;
}
结果是一个看不懂的二进制文件
如果在VS上打开:
可以看到存储的是 10 27 00 00,,就是10000
4、 流的打开与关闭
4.1 流和标准流
4.1.1 流
我们程序的数据需要输出到各种外部设备,也需要从外部设备获取数据,不同的外部设备的输入输出操作各不相同,为了方便程序员对各种设备进行方便的操作,我们抽象出了流的概念,我们可以把流想象成流淌着字符的河。
C程序针对文件、画面、键盘等的数据输入输出操作都是通过流操作的。
一般情况下,我们要想向流里写数据,或者从流中读取数据,都是要打开流,然后操作。
4.1.2 标准流
问题: 在使用C语言写程序时,使用scanf从键盘输入数据或者使用printf向屏幕输出数据为什么没有打开流和关闭流的操作呢?
原因就是C语言程序在启动的时候,默认打开了3个流:
• stdin - 标准输入流,在大多数的环境中从键盘输入,scanf函数就是从标准输入流中读取数据。
• stdout - 标准输出流,大多数的环境中输出至显示器界面,printf函数就是将信息输出到标准输出 流中。
• stderr - 标准错误流,大多数环境中输出到显示器界面。 这是默认打开了这三个流,我们使用scanf、printf等函数就可以直接进行输入输出操作的。
stdin、stdout、stderr 三个流的类型是:FILE*
,通常称为文件指针。
在C语言中,就是通过FILE*
的文件指针来维护流的各种操作的。
4.2 文件指针
缓冲文件系统中,关键的概念是“文件类型指针”,简称“文件指针”。每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息,如文件的名字,文件状态及文件当前的位置等。这些信息是保存在一个结构体变量中的。该结构体类型是由系统声明的,取名FILE.
定义pf是一个指向FILE类型数据的指针变量。可以使pf指向某个文件的文件信息区(是一个结构体变量)。通过该文件信息区中的信息就能够访问该文件。也就是说,通过文件指针变量能够间接找到与它关联的文件。
文件是在硬盘上的,文件信息区是在内存上的!
4.3 文件的打开和关闭
文件在读写之前应该先打开文件,在使用结束之后应该关闭文件。
在编写程序的时候,在打开文件的同时,都会返回一个FILE*的指针变量指向该文件,也相当于建立了指针和文件的关系。
ANSI C 规定使用 fopen 函数来打开文件,fclose 来关闭文件。
//打开文件
FILE * fopen ( const char * filename, const char * mode );
// 文件名 文件的打开方式
返回的就是FILE*的指针,就是文件信息区的地址,然后就能找到文件信息区,就能找到流,然后进行读写操作
//关闭文件
int fclose ( FILE * stream );
mode表示文件的打开模式,下面都是文件的打开模式:
代码:
int main()
{
//打开文件
//打开成功返回有效的文件指针
//打开失败返回NULL
FILE* pf = fopen("data.txt", "w");//只写
if (pf == NULL)
{
perror("fopen");
return 1;
}
//写文件
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
若文件路径下没有data.txt的文件,在只写的情况下,会自动在文件路径下创建一个data.txt文件,然后可以进行文件的写操作
若文件路径下有data.txt文件,并且文件中有内容,在只写的情况下会清空文件中的内容
执行程序前:
执行程序后:
代码:举例“w”和“r”
int main()
{
//打开文件
//打开成功返回有效的文件指针
//打开失败返回NULL
FILE* pf = fopen("test.txt", "r");//只读
if (pf == NULL)
{
perror("fopen");
return 1;
}
//读文件
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
文件路径下没有test.txt文件,只读的话会报错
假如文件现在不在当前程序的路径下,在桌面该怎么打开?
我们就需要再在文件名之前添加文件的路径,如果能找到该文件,则文件内容会被清空
代码:
int main()
{
//打开文件
//打开成功返回有效的文件指针
//打开失败返回NULL
FILE* pf = fopen("C:\\Users\\Administrator\\Desktop\\test.txt", "w");//只写
// 这也叫做绝对路径
if (pf == NULL)
{
perror("fopen");
return 1;
}
//写文件
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
若文件在该工程所在路径的上一级路径该怎么办?
int main()
{
//打开文件
//打开成功返回有效的文件指针
//打开失败返回NULL
FILE* pf = fopen(".\\..\\test.txt", "w");
//这叫做相对路径
//. 表示当前路径
//.. 表示上一级路径
if (pf == NULL)
{
perror("fopen");
return 1;
}
//写文件
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
文件被清空,说明文件操作成功!
5、文件的顺序读写
5.1 顺序读写函数介绍
上面说的适用于所有输入流一般指适用于标准输入流和其他输入流(如文件输入流);
所有输出流一般指适用于标准输出流和其他输出流(如文件输出流)。
5.1.1 fputc与fgetc
fputc:
int fputc ( int character, FILE * stream );
// 输入的内容 文件指针
代码:
int main()
{
//打开文件
FILE* pf = fopen("test.txt", "w");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//写文件
for (int i = 'a'; i <= 'z'; i++)
{
fputc(i, pf);
// 内容 文件指针
}
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
程序执行结果:项文件中写入26个英文字母
fgetc:
int fgetc ( FILE * stream );
// 文件指针
若文件读取成功,返回字符的ASCII值;
若文件读取失败,返回EOF(文件结束标志);
int main()
{
//打开文件
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//写文件
int ch = 0;
while ((ch = fgetc(pf)) != EOF)
{
printf("%c ", ch);
}
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
程序执行结果:
以上就是上篇的全部内容啦!下篇更精彩哦!希望大家多多点赞支持!
如果有什么问题,欢迎私信!