1. 概述

文件分为两种:

  1. 磁盘文件:指一组有关数据的有序集合,通常存储在外部介质(如硬盘)上,使用时才调入内存。
  2. 设备文件:设备文件:操作系统中,把每个与主机相连的的输入输出设备看作一个文件,把他们的输入输出作为磁盘的读写。

磁盘文件分类:

  1. 文本文件:基于字符编码的文件,可以用文本编辑器直接打开,并且数以ASCII编码形式存在。
  2. 二进制文件:基于值编码文件,数字的存储以二进制形式,内存中数据按照在内存中的原样输出到磁盘。

除了文本文件其他的基本都是二进制文件。(如图片,音频等)


2. 文件的打开关闭

文件指针:用指针指向文件的指针。(FLIE*)

当打开文件时文件会放在缓冲区中。

打开文件的函数:fopen

1
FILE*P=fopen("文件地址",读取方式);//路径地址用“/”

读取方式有以下几种:

打开模式 意义
r/rb 以只读方式打开一个文件(不会自动创建文件,如果不存在文件就会报错)
w\wb 以写的方式打开文件(如果文件不存在,系统就会创建一个文件,如果文件有内容,则会覆盖原内容)
a/ab 以追加方式打开文件,在末尾添加内容(如果不存在,系统会自动创建一个文件)
r+/rb+ 以可读可写的方式打开文件(不会创建新文件)
w+/wb+ 以可读可写的方式i打开一个文件(如果文件存在就会覆盖原文件内容,文件不存在则创建一个文件)
a+/ab+ 以添加方式打开文件,在文件末尾更改(如果文件不存在则会创建一个文件)

在文件打开后我们应该将文件关闭。使用fclose函数

1
2
int fclose(FILE*p);
//如果成功,则会返回0,如果失败则会返回-1
  • 一个程序进程能打开的文件是有限制的。
  • 如果文件未关闭,那么操作系统会在进程结束后统一关闭

读取出错原因可能有:

  1. 找不到文件(路径有误)。
  2. 文件权限限制。
  3. 文件同时打开个数上限。(最多65535个)

3. 文件的读写

文件读取:

我们在读写字符文件时使用fgetc和fputc函数用法如下:

1
int fgetc(文件指针);

成功时会返回读取到的字符,失败为-1;

示例:

1
2
3
4
5
6
7
8
9
10
11
//假设我们创建了个txt文本文件,里面写了个A

FILE*p=fopen("D:/Desktop/A.txt","r");
if(!p){
printf("文件打开失败!\n");
return -1
}

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

最后输出结果为A

注意:

那当我们输出字符串时不需要对指针进行移动,因为 在文件读取中,其中的光标在读取完文件一个字符后会自动往前进一格。所以只需要循环就行了。并且修改文件指针会出错,所以不能修改文件指针。 在文件结尾默认是-1,原因是在文本文件中是以ASCII码存储,都为正,汉字虽然是负数名单时-1不表示汉字。所以结尾为-1。并且文件结尾使用EOF表示==(以上规则只适用于文本文件)==,一般在文件开头就用define定义EOF为-1。

如果为二进制文件则可以使用feof函数判断文件是否结束,并且feof函数既可以判断二进制文件也可以判断文本文件。当到文件结尾时返回值为非0数,没到时为0(判断的时最后一次读取操作)


文件写入

文件写入时我们在文件打开方式中应该先换为w。

写入用fputc函数格式为

1
fputc(字符,文件指针);

示例:

1
2
3
4
5
6
7
8
9
;FILE*p=fopen("D:/Desktop/A.txt","w");
if(!p){
printf("文件打开失败!\n");
return -1
}

char ch='A';
fputc(ch);
fclose(p);

在文件写入中出错概率比单纯读取文件出错概率小,在文件损坏或文件的路径有误时文件会被直接创建,所以写入文件出错一般为:

1. 文件打开上限。
1. 文件的权限限制

在写入过程中,如果问我们加上循环就可以在文件里编写大量文段

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
FILE*p=fopen("D:/Desktop/A.txt","r");
FILE*p1=fopen("D:/Desktop/a.txt","w");
if(!p){
printf("文件打开失败!\n");
return -1
}

char ch;
while((ch=fgetc(p))!=EOF){
scanf("%c",&ch);
if(ch=='#')
break;
fputc(ch,p);
}
fclose(p);

4. 文件的加密解密

文件加密解密的基本原理时基于字符由ASCII码存储,所以,我们在输入狗移动字符对应的数字即可改变内容,在解密时以相同的方式相反移动同样的大小就能恢复。

例子:

(A.txt用来显示正常文件,a.txt用来显示加密文件)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#define EOF -1

FILE*p=fopen("D:/Desktop/A.txt","r");
FILE*p1=fopen("D:/Desktop/a.txt","w");
if(!p){
printf("文件打开失败!\n");
return -1
}

char ch;
while((ch=fgetc(p)) != EOF){
ch++;
fputc(ch,p1);
}
fclose(p);
fclose(p1);

这时我们会得到一份a.txt文件即为加密后的文件,如果相对a.txt文件解密,只需要在加密基础上倒过来ch–就可以了。


5. 文件行的读写

文件读取

我们使用fgetc进行文件行的读取

基本格式如下

1
char* fgets(字符串指针,最大长度,文件指针);

示例:

1
2
3
4
5
6
7
8
9
10
11
12
FILE*p=fopen("D:/Desktop/A.txt","r");
if(!p){
printf("文件打开失败!\n");
return -1
}

char* pp=(char*)malloc(sizeof(char)*100);
memset(pp,0,100);
fgets(pp,100,p);
printf("%s\n",p);
free(pp);
fclose(p);

注意:

在操作中,==我们设定的大小中会预留一个位置存储“\0”,即我们设置的为100个位置,有效字符位置只有99个==。当读取到换行时,会自动换行,并且会结束读取 。在一轮读取后下次读取时依旧会以现在的位置继续读取,即光标会自动移到下一位。

循环读取示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
FILE*p=fopen("D:/Desktop/A.txt","r");
if(!p){
printf("文件打开失败!\n");
return -1
}

char* pp=(char*)malloc(sizeof(char)*100);
while(!feof(p))//当文件到了结尾返回0,没到时返回为非0值
{
memset(pp,0,100);
fgets(pp,100,p);
printf("%s\n",p);
}
free(pp);
fclose(p);

上述代码中每次我们都会执行一次memset是为了防止上次读取污染本次读取。


文件写入

我们使用fputs进行行写入

基本格式如下:

1
fputs(常量字符串,文件指针);

当fputs在字符串中遇到\n时也会进行换行操作,遇到\0直接停止。

示例演示:

1
2
3
4
5
6
7
8
9
FILE*p=fopen("D:/Desktop/A.txt","w");
if(!p){
printf("文件打开失败!\n");
return -1
}
char ch[]="这是一个测试";

fputs(ch,p);
fclose(p);

连续的输入如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
FILE*p=fopen("D:/Desktop/A.txt","w");
if(!p){
printf("文件打开失败!\n");
return -1
}
char*pp=(char*)malloc(sizeof(char)*1024);
while1){
memset(p,0,1024);
scanf("%[^\n]",pp);//接收除了换行以外的所有输入
getchar();//防止打完第一行后卡住无法换行
if(!strcmp(p,"cmd=exit")//也可使用strncmp(p,"cmd=exit",8))
break;
stract(pp,"\n");//追加换行符
fputs(pp,p)
}

资料参考

b站的黑马程序员