什么是文件和什么是文件操作
一、文件的基本知识和原理
1.首先我们应该要知道什么是文件:
例如:在我的电脑中的磁盘中的文件,这些就是文件,但在程序设计中一般的文件有两种:
(1.)程序文件(包括源程序文件(后缀 .c)、目标文件(后缀 .obj)、可执行程序(后缀 .exe))
(2.)数据文件(文件内容不一定是程序,而是程序运行时读写的数据,比如程序运行时需要从中读取数据的文件,或者输出内容的文件),解释一下,其实数据文件就是你不仅可以从里面拿东西出来还可以放东西进去的文件
(3.)之间的关系:程序文件可以对数据文件进行操作
2.什么是文件名
(1.)一个文件一定要有一个唯一的文件标示,这样才可以方便我们拿出来用和存放数据
文件名包括3部分:文件路径+文件名主干+文件后缀
3.什么是文件类型
(1.)根据数据的组织形式,数据文件被称为文本文件或者二进制文件
(2.)数据原始在内存中存放是以二进制的形式存储的,如果不加转换就输出到外存,那么你看到的就是一个二进制的文件(天书)
(3.)总的来说文本文件就是我看的懂的,二进制文件就是我看不懂的
(4.)关系:文本文件就是通过二进制文件进行通过ASCII值的转换,以ASCII值中的相对应的字符的形式存储在外存中就叫文本文件
4.数据在内存中的存储形式
(1.)数据一般包含两种:
1.一种是字符类型
2一种是数值类型
(2.)而在内存中存储时,字符类型是以ASCII值的形式存储的,数值类型数据则可以用二进制形式存储,也可以用ASCII值的形式存储
(3.)这边举一个例子:
比如我要在内存中存储一个整数10000,此时就有两种存储方式:
1.用二进制的形式
2.用文本的形式
假如用二进制的形式,这边就会让我的10000这个数字变成一个二进制的序列(但是在内存中是以16进制表示的)10 27 00 00 ,所以此时这个10000在我的内存中所占的空间大小就是32个比特位(4个字节),然而当我用文本的形式(以ASCII值的形式)输出到磁盘上时,我的磁盘上就会占用5个字节的空间(每个字符一个字节),所以这就是用二进制的形式和文本形式的最大的区别了
然后根据上述所说这边还有一个点要注意一下,10 27 00 00就是这个16进制的写法,因为我们的电脑大部分都是使用小端存储的形式,所以当我们的10000的源码在存储时,是以小端存储的,所以在内存中是10 27 00 00这样的,然而10000的16进制源码却是 00 00 27 10,这个主要就是涉及到数据的转换的知识了,下次我们再讲
5.什么是文件缓冲区
(1.)当我们在处理数据文件时,缓冲文件系统会为我们自动在内存中为程序开辟一块文件缓冲区,当我们在从内存向磁盘输出数据时,此时数据会被先送到内存中的缓冲区,当缓冲区装满后才一起送到磁盘上
(2.)同理当我们要从磁盘上读取数据时,此时则从文件中读取数据输入到内存缓冲区,当缓冲区充满时,再从缓冲区逐个地将数据送到程序数据区
(3.)并且缓冲区的大小由c编译系统决定
如下图:这个就是具体的文件缓冲区在内存中的图示
就上上述文字更方便理解
(4.)总的来说知道有这个东西的存在就行,具体如何实现的……不好用文字解释
6.对输入输出缓冲区的理解:
为什么要引入缓冲区:
(1.)我们从磁盘里取信息,我们先把读出的数据放在缓冲区,计算机再直接从缓冲区中取数据,等缓冲区的数据取完后再去磁盘中读取,这样就可以减少磁盘的读写次数,再加上计算机对缓冲区的操作大大快于对磁盘的操作,故应用缓冲区可大大提高计算机的运行速度。
(2.)在使用打印机打印文档,由于打印机的打印速度相对较慢,我们先把文档输出到打印机相应的缓冲区,打印机再自行逐步打印,这时我们的CPU可以处理别的事情。
(3.)所以缓冲区就是一块内存区, 它用在输入输出设备和CPU之间,用来缓存数据 。它使得低速的输入输出设备和高速的CPU能够协调工作 ,避免低速的输入输出设备占用CPU,解放出CPU,使其能够高效率工作。
7.缓冲区的三种类型(全缓冲、行缓冲、无缓冲)
(1.)全缓冲:在这种情况下,当填满标准I/O缓存后才进行实际I/O操作。全缓冲的典型代表是 对磁盘文件的读写 。
(2.)行缓冲:在这种情况下,当在输入和输出中遇到换行符时,执行真正的I/O操作。这时,我们输入的字符先存放在缓冲区,等按下回车键换 时才进行实际的I/O操作。典型代表是 标准输入(stdin) 和 标准输出(stdout) 。
(3.)不带缓冲:也就是不进行缓冲,标准出错情况stderr是典型代表,这使得出错信息可以直接尽快地显示出来
8.什么是文件指针
(1.)首先在我们使用fopen打开文件时,此时这个文件都会返回一个FILE的指针变量指向该文件,相当于此时文件进行了备份,指针指向了备份文件,这样就很好的建立了指针和文件之间的关系了,所以就可以通过使用这个指针来进行对我的文件的各种操作,对文件中所包含的内容进行操作了
(2.)图例如下:
(3.)以上就是文件指针的使用(前提是文件打开成功了)
以上就是文件的基本知识和原理
二、文件的操作
1.如何打开文件
(1.)打开文件我使用的是一个fopen函数,这个函数的使用形式为
FILE* fopen(const char* filename,const char* mode)
其中filename表示文件名的意思
mode表示的是打开的模式是那种
char* filename这个表示的是我在进行传文件的时候,传的是一个首字符的地址,所以此时用一个char*的指针接收
所以我在打开文件时必备的两个参数是(文件名和打开方式)
2.文件的打开方式(最全表格)
如下图:
(3.)所以打开文件的具体代码如下:
包含文件名和打开方式就行(相对路径的写法)
fopen("test_我的文件操作", "r");
绝对路径的写法
fopen("D:\\我的c语言\\文件操作\\test_我的文件操作\\test_我的文件操作", "r");
当我们写成绝对路径时(要注意 \ 会转义我的字符,所以我要写两个 \ 防止路径被破坏)
(4.)如何表示上一路径
. 表示当前路径 fopen("test_我的文件操作", "r"); .. 表示上一级的路径 fopen("../test_我的文件操作", "r"); 上一路径的上一路径 fopen("../../test_我的文件操作", "r");
打开文件的完整写法
FILE* pf = fopen("test_我的文件操作", "r");
(5.)所以对一个文件进行具体操作
代码如下:
#include<stdio.h> #include<string.h> int main() { FILE* pf = fopen("test.txt", "r"); //然而此时打开文件也有可能失败(失败之后就会返回一个NULL,成功就返回一个正常的指针) //所以此时这里就要加一个判断条件 if (pf == NULL) { printf("%s",strerror(errno)); //打不开,自然而然,这边要写一个return 0; return 0; } //打开成功 //读文件 //读完文件 //关闭文件 fclose(pf);//因为此时的pf指向的是我打开的那个文件,所以想要关闭那个文件,就只需要把pf给fclose就行 pf = NULL;//但是此时这个pf还是指向我文件的那个地址,所以此时要把其赋成NULL,这样才不会出问题(有点像free) return 0; }
1.fclose(pf); 这个就是如何进行关闭文件的操作,因为此时的pf指向的是我打开的那个文件,所以想要关闭那个文件,就只需要把pf给fclose就行,fclose就是代表我的关闭文件的函数
2.当我判断完文件是否打开成功之后就可以进行我的相应的对文件的操作了(读文件或者写文件),就是从文件中拿东西出来还是放东西到我的文件中去
三、文件读写的函数使用
上述讲述了对文件的使用,现在我们就讲一下如何用各种文件函数对文件进行使用
1.首先fputc和fgetc函数的使用(字符操作)
(一、)fputc(写)函数的使用
(1.)fputc的使用形式:int fputc ( int c,FILE*stream);
意思就是在文件流(stream)中,写入我的一个字符(int c)
(2.)所以在文件中写入一个字符的前提就是我要先打开这个文件,打开文件后才可以进行对我的文件进行各种操作,写入或者读取或者别的
(3.)所以具体代码如下:
#include<stdio.h> #include<string.h> int main() { FILE* pfWrite = fopen("test.txt", "w"); if (pfWrite == NULL) { printf("%s", strerror(errno)); } //文件操作 fputc('h', pfWrite); fputc('e', pfWrite); fputc('l', pfWrite); fputc('l', pfWrite); fputc('o', pfWrite); fclose(pfWrite); pfWrite = NULL; return 0; }
(4.)上述的文件操作就是运用了我的fputc这个文件操作函数,对文件进行写入内容(一次一个字符 写入)
(5.)所以这时我的程序运行起来后,然后我再去打开之前创建的那个“test.txt”文件,此时文件中就从什么都没有变成里面放入了一个hello的内容,如图:
我点进我的test.txt文件:就出现了hello
(二、)fgetc(读)函数的使用
(1.)大致方法一样只是,函数换一下而已,所以对文件的打开和关闭同理
(2.)使用形式:int fgetc(FILE*stream)
(3.)所以具体读文件的代码如下:
#include<stdio.h> #include<string.h> int main() { FILE* pfRead= fopen("test.txt", "r"); if (pfRead == NULL) { printf("%s", strerror(errno)); } //文件操作 printf("%c", fgetc(pfRead)); printf("%c", fgetc(pfRead)); printf("%c", fgetc(pfRead)); printf("%c", fgetc(pfRead)); printf("%c", fgetc(pfRead)); fclose(pfRead); pfRead = NULL; return 0; }
输出内容如下:
(4.)这两个文件操作函数唯一的两个区别在于:
1.函数的使用情况不同,一个是读文件,一个是写文件
2.还有最重要的一个区别就是,在打开文件时,一个是用 " r "的形式打开,一个是以 "w"的形式打开
3.所以文件的打开形式一定要与我的文件操作函数相对应
(5.)所以以上就是对fputc和fgetc函数的使用
接下来我们讲一下什么是标准输入设备,什么是标准输出设备
2.什么是标准输入设备,什么是标准输出设备
(1.)标准输入设备(键盘)stdin
(2.)标准输出设备(屏幕)stdout
这些是程序默认打开的两个流设备,只要我的一个代码运行起来就一定会默认打开3个流,键盘和屏幕就是其中的两个流,还有一个就是stderr(因为键盘和屏幕是默认打开,所以当我们使用printf和scanf时才可以正常进行)具体例子如下:
int ch = fgetc (stdin);这句代码的意思就是从标准输入流中读取信息一个字符的意思,然后存到ch变量中(再直接一点,就是从我的键盘中读取),所以从标准输入流中读取就是从键盘中读取,就是我直接输入,所以当我们使用(标准输入输出)时其实就是向屏幕写,从键盘读,也就是我们在写代码时使用的头文件 #include<stdio.h>,一个标准输入输出函数,所以此时我们使用printf和scanf时,就可以正常使用(向屏幕写,从键盘读)的功能
3.fgets 和 fputs 函数的使用(文本语句操作)
(一、)fgets(读取)函数的使用
(1.)使用形式:char* fgets(char*string,int n ,FILE * stream
意思为从一个流文件(FILE * stream)读取最多n个字符的信息到char * 指针指向的字符数组中去也就是(char * string这个字符数组中)
(2.)具体使用使用情况如下:
但是这边有一个小细节点
(3.)进行对比上述两幅图,可以知道当我在打印的时候如果加上’\n’这个换行符和不加是有区别的,加了就会进行两次换行,不加就只进行一次换行(所以这边我们可以得出结论:就是当我们在使用fgets这个函数的时候,将流文件放入我的数组中时,这个读取操作不仅会将流文件中的所有信息放进我的数组中,而且连我的 ‘\n’ 这个换行也会被读取到我的数组中,所以此时就导致了两次换行的问题)(前提是我读取文件时文件内部是有换行的)