文件操作的相关知识点总结和程设中的演示程序的详解
文件分类
文件分为文本文件(.txt)和二进制文件
文本文件:保存的时候,每一个字符对应一个字节
二进制文件:二进制编码保存的文件
设备文件
当启动一个程序的时候,系统会打开3个设备文件
stdin:标准输入文件(鼠标,键盘),默认情况下,标准输入设备是硬盘
stdout:标准输出文件(显示器),默认情况下,标准输出设备是显示器
stderr:标准错误文件,一般为显示器
文件的重定向
重定向符号:
“<” 输入重定向
">"输出重定向
以下面这个程序为例:
#include<stdio.h>
int main()
{
int i;
int a[5];
printf("input 5 numbers:\n");
for(i=0;i<=4;i++)
scanf("%d",&a[i]);
printf("the 5 numbers are:\n");
for(i=0;i<=4;i++)
printf("%d,",a[i]);
return 0;
}
这个程序就是只有标准输入输出,即我可以直接在编译器中运行,得到的结果是这样的:
重定向:将标准输入换成文件输入输出,即输入流改为data1.txt这个文件,将结果输出到data2.txt中。
方法:在放程序的这个文件夹中新建data1.txt,输入1,2,3,4,5并保存。在在文件资源管理器中找到本程序的exe文件所在的位置,在cmd中输入可执行程序的名字和重定向的位置,就可以在新建的data2.txt中得到输出结果
文件访问方式
模式 | 描述 |
---|---|
r | 只读的方式打开。不创建文件,如果文件不存在会报错 |
w | 只写的方式打开。如果文件不存在,则会创建一个新文件。如果文件存在,则会先清空文件中原来的内容,在重新写入。 |
a | 追加的方式打开。如果文件不存在,则会创建一个新文件。如果文件存在,会在已有的文件内容中追加内容。 |
r+ | 可读可写的方式打开,不创建新文件 |
w+ | 可读可写的方式打开。如果文件已存在,则文件会被截断为零长度,如果文件不存在,则会创建一个新文件。 |
a+ | 允许读写文件。如果文件不存在,则会创建一个新文件。读取会从文件的开头开始,写入则只能是追加模式。 |
如果处理的是二进制文件,则需要使用下面的访问方式:
"rb", "wb", "ab", "rb+", "r+b", "wb+", "w+b", "ab+", "a+b"
常用的就是“r”和“w”,r:不创建也不清空,w:会创建也会清空
打开文件:fopen
语法:FILE *fopen(const char *文件名,"文件访问模式")
返回值:成功:指向该文件的文件流的指针(即FILE结构体的地址)
失败:NULL
例子:
FILE*fp=fopen("./a.txt","r");
if(fp==NULL)
{
perror("Error");
return ;
}
perror() 函数:把错误消息输出到标准错误 stderr。
语法:void perror(const char *str)
格式:输出字符串 str,后跟一个冒号,然后是一个空格,然后是错误信息
如果此文件夹下没有a.txt的文件,则会输出Error: No such file or directory
关闭文件:fclose
语法:int fclose (FILE * fp) ;
返回值:如果成功关闭文件,则返回0,如果关闭文件时发生错误,则返回EOF。
文件的顺序读写:
按照字符读写文件:fputc,fgetc
- 读文件:fgetc(从给定输入流中读取下一个字符)
-
语法:
int fgetc(FILE* stream) ;
-
返回值:成功时返回将读取到的字符转化为int类型的字符,失败时返回EOF
注意:fgetc常与feof配合使用,如下面这个例子实现了把fp1的内容拷贝到fp2中去,并在读取完成后时退出循环。
补充:feof 的功能时检查本字符的下一个字符是否已经抵达给定文件流的结尾,如果抵达则返回非零,如果未抵达则返回0
while(1){
char ch = fgetc(fp1);
if(feof(fp1)){
break;
}
fputc(ch,fp2);
}
- 写文件:fputc(将一个字符写到文件中)
-
语法:
int fputc(int ch,FILE*fp)
-
功能:将char转化为unsigned char后写入fp文件中
-
参数:ch:需要写入的文件的字符
stream:文件指针(所以在此之前需要用fopen获得文件的指针)
-
返回值:成功:返回成功写入的字符
失败:返回EOF
示例:
int main(){
//打开文件
FILE*fp = fopen("./a.txt","w");
char s[]="abcd";
int i=0;
//将字符串写入文件
while(s[i]){
fputc(s[i],fp);//后续都会按照次序依次“流入”文件流中,因为文件指针会默认后移,而不是每次循环的时候都从头
i++;
}
//关闭文件
fclose(fp);
return 0;
}
按照行读写文件:fgets,fputs
-
读文件:fgets(只能操作字符串,泵操作二进制文件)
-
语法:
char*fgets(char *str,int size,FILE *stream)
-
参数:str:指向字符串的指针,size:你指定的最大读取字符串的长度(会自动加"/0"所以只能读n-1个)stream:文件指针
-
功能:从stream指向的文件中读取字符,保存到str所志昂的内存空间中,直到出现①换行符②读到文件结尾③读了size-1个字符为止
-
返回值:成功:成功读取的字符串首元素的地址
失败:读到文件结尾或者出错:NULL(空指针)
示例:
a.txt
‘a’ ‘b’ ‘\n’
‘c’ ‘\0’ ‘d’ ‘e’ ‘f’ ‘g’ ‘j’ ‘\n’
‘\0’ ‘x’ ‘y’ ‘\n’
char buf[5]; FILE*fp = fopen("a.txt","r"); fgets(buf,5,fp);
一共需要读4次,每次存放到buf中的内容如下:
第一次: a b ‘\n’ ‘\0’ [遇到换行符就终止,并且加上’\0’]第二次:c ‘\0’ d e ‘\0’ [size=5,所以最多只能读取4个字符]
第三次:f g j ‘\n’ ‘\0’ [遇到换行符]
第四次:‘\0’ x y ‘\n’ ‘\0’
-
-
写文件:fputs
-
语法:int fputs(const char *str,FILE *stream)
-
功能:将str所指向的字符串写入到stream所指向的文件中,且字符串中的结束符’\0’不会写入文件
-
返回值:成功:非负值
失败:EOF ,遇到’\0’就结束了,所以中间有’\0’就终止读入了
-
文件路径
-
绝对路径:目标文件在磁盘上的真实路径,比如:D:\A\bupt\高数
-
相对路径:
引用上级文件: …/1.jpg
引用同级文件:1.jpg
引用下级文件:picture/1.jpg
引用上上级文件:…/…/1.jpg
简易文件压缩
前置知识:
-
int main(int argc,char* argv[ ])
argc(argument counter):是命令行总的参数个数
argv[](argument value):指针数组,用来存放指向命令行参数(字符串)的指针,每个元素指向一个参数。
argv[0] : 可编译程序(.exe)的在电脑中绝对路径
argv[argc]:NULL
-
int fprintf( FILE *stream, const char *format, ... );
类似与printf,format可以是%s,%d等等
示例:
a.txt 内容:小熊
#include<stdio.h> int main() { FILE*fp=fopen("./a.txt","a"); fprintf(fp,"%s %s %s","喜欢春天"," 我也喜欢春天"," 你呢"); fclose(fp); return 0; }
运行后:
a.txt内容:小熊喜欢春天 我也喜欢春天 你呢
所以
fprintf(stderr, "Usage: %s filename\n", argv[0]);
的意思是将错误信息写进stderr这个标准错误文件中。 -
exit()
exit(0)代表程序正常退出,其余都表示异常终止,可以通过返回的具体的数值来判断出错的根源在哪里
-
“<” 输入重定向
">"输出重定向
代码详解:
#include <stdio.h>
#include <stdlib.h> // for exit()
#include <string.h> // for strcpy(), strcat()
#define LEN 40
int main(int argc, char *argv[])
{
FILE *in, *out;
int ch;
char name[LEN];
int count = 0;
// 检查命令行参数
//如果命令行的参数等于1,则不用压缩,因为本程序是将每三个字符压缩成1个字符,所以在标准错误输出中弹出错误提示信息
if (argc < 2)
{
fprintf(stderr, "Usage: %s filename\n", argv[0]);
exit(1);
}
//argv[1]:作为输入流参数的文件的名字,如果文件打开失败,则在标准输出中弹出无法打开文件
if ((in = fopen(argv[1], "r")) == NULL)
{
fprintf(stderr, "I couldn't open the file \"%s\"\n",
argv[1]);
exit(2);
}
//将输入的文件名字字符串拷贝到name字符数组中
strcpy(name,argv[1]);
//将name字符数组后面追加上后缀,即.red
strcat(name,".red");
//打开name这个文件夹,(如果你将a.txt作为输入流,那么这时候name字符串就是a.txt.red,打开的就是待压缩的文件),因为是以只写的方式打开,且之前并没有这个文件,所以会新建这个文件。
//下面这个if是判断如果打开文件失败,则在标准错误输出中输出“不能创建output文件”,并exit(3)
if ((out = fopen(name, "w")) == NULL)
{ // open file for writing
fprintf(stderr,"Can't create output file.\n");
exit(3);
}
//压缩文件,用getc(in)) != EOF判断是否读到了文件末尾,每隔三个字符将其中的第一个字符写入out所指向的文件中(也就是a.txt.red)
while ((ch = getc(in)) != EOF)
if (count++ % 3 == 0)
putc(ch, out);
//关闭文件
if (fclose(in) != 0 || fclose(out) != 0)
fprintf(stderr,"Error in closing files\n");
return 0;
}
方法:
在程序同一个目录下创建一个a.txt,然后再命令行里输入
即程序名+空格+待压缩文件