10_文件
- 文本文件:基于字符编码,如ASCII、UNICODE
- 二进制文件
文件打开
FILE *fopen(filename, mode);
// 系统自己定义了一个结构体,叫做FILE
// mode表示打开文件的模式
/*
mode的取值
r rb 以只读方式打开
w wb 以写方式打开
a ab 以追加方式打开,在末尾添加内容
r+ rb+ 以可读可写方式打开,不创建新文件
w+ wb+ 以可读可写方式打开,文件如果存在则清空
a+ ab+ 以添加的方式打开文件
Tips:b是指二进制模式,windows专用;
*/
FILE *fp = fopen("xx.txt","r");
if(fp == NULL)
{
printf("文件打开失败");
return;
}
printf("打开失败");
fclose(fp); //关闭文件
/*
文件打开失败有几种情况
1、找不到文件,路径不对
2、没有读写权限
3、程序打开文件的数量超出上限(一般是限制65535个文件);
*/
fputc('A',fp); // 覆盖写入
char ch = fgetc(fp); // 读取一个字符
while(ch == fgetc(fp) != EOF)
/*
文件结尾 EOF 默认值是-1;
用一次fgetc,就会从文件中读取一个字符,并且文件中的光标会向前走一步;
*/
char ch;
while((ch = fgetc(fp)) != EOF)
{
printf("%c\n",ch);
}
// EOF的ASCII值为-1,而ASCII中字符的值全为正,所以可以用来作为结束标志;
char ch = 'a';
FILE *fp = fopen("./b.txt","a");
fputc(ch,fp);
ch = 'b';
fputc(ch, fp); // 此时b.txt文件内就有了字符串ab
// 例、实现一个vi编辑器
scanf("%s",fileName);
getchar(); // scanf的结束时用\n,getchar则是用来接收\n,避免多次scanf导致问题;
// 更新缓冲区,比如说录入的时候终端了程序,原有的输入内容用fflush就会被缓存下来;
fflush(p);
// 目标:使用命令 myvi ./a.txt 就可以对a.txt进行编辑
// 例、实现cat,即查看文本文件;
// cat ./a.txt 此时就会显示出文件的所有内容
// 例、四则运算
sprint(buf, "%d%c%d=\n",a,b,c);
// 例如键入2*3=\n,就会放入buf中
// 文件的加密解密
/*
简单的加密
1、读取文件,将里面的字符的ASCII码全部加1,
2、将读取后处理的内容写入到另外一个文件中;
解密
1、读取文件,讲礼貌的字符的ASCII码全部减1,
2、将处理后的内容写入到另一个文件中
Tips:系统md5就是一种常用的加密方式;
*/
按字符读写文件 → 每次使用则读取一个字符
- 读 fgetc()
- 写 fputc()
- 是否到文件结尾 feof()
按行读写文件 → 也叫块读取,可以指定读取的长度
- 读 fgets()
- 写 fputs()
char buf[1024];
fgets(buf, 5,fp);
/*
fp是通过fopen获取到的fileStream
5是读取的数量,在实际读取时,传入5,会读4个字符,还剩1个字符为\0作为字符的结束;
读取的数量可以超过fp的大小
*/
// char 直接定义的buf存放到栈里面,空间有限
char buf[1024];
// 使用malloc申请的空间在堆空间内,空间很大
char *uf = malloc(sizeof(char *) * 1024);
while(feof(fp) == 0){}
/*
feof()判断文件是否到了结尾
=0 说明没有到结尾
≠0 说明已经到了结尾
Tips:EOF是判断字符的结尾,而feof()则是判断文件流是否到末尾
*/
/*
字符串的格式化读出:从buf中,按照"%d%c%d=\n"的格式,提取各个变量值,赋值到abc当中
*/
sscanf(buf, "%d%c%d=\n",&a,&b,&c);
/*
文件的格式化写入:将a b c value按照"%d%c%d=%.2f\n"的格式组成字符串,存入到buf中
*/
fprintf(buf, "%d%c%d=%.2f\n",a,b,c,value);
// 上面这句等价于
memset(buf,0,20);
sprintf(buf,"%d%c%d=%.2f\n",a,b,c,value);
fputs(buf,fp2);
/*
文件的格式化读取
*/
fscanf(fp1, "%d+%d=%d\n",&a, &b, &c);
- scanf() - printf()
- sscanf() - sprintf()
- fscanf() - fprintf()
printf("===%5d===",1);
/*
%5d ____1,前面四个空格
%-5d 1____,后面四个空格
%.5d 00001
%-.5d 00001
%ld 打印long类型
*/
// 例、使用fscanf(),fprintf()实现四则运算写入
// 例、使用结构体完成四则运算读写
// 例、10000个数据排序
/*
Tips:第一个想到的是冒泡排序,但是冒泡的执行次数10000+9999+9998+...
100000个数据排序,冒泡排序用时35s
*/
// 如何记录运行时间?
unsigned int start_time = time(NULL);
...中间执行代码操作...
int end_time = time(NULL);
end_time - start_time → 即为程序运行时间
/*
Tips:对于有规律的数,可以用空间换时间,
例如,100000个1-1000的数,可以定义一个arr[1000],某数i出现的次数作为arr[i]的值
此时可以缩短排序时间到1s
*/
——————————————————————————————————————————————
按块读写
fread(*ptr , size_t , nmemb , stream);
- ptr 要读写的地址
- size_t 块的大小
- nmemb 块数
- stream 文件流
fwrite( )
总的读写大小 = 块的大小 * 块数
// 移动读写的光标
FILE *fp = fopen("../../d.txt", "r");
fseek(fp, 6 , SEEK_SET);
fseek(fp, -5 , SEEK_END);
// 光标向前走n个位置,即使文件光标已经到了开头,仍会有一个相对距离
ftell(fp); 返回到当前文件的读写位置
rewind(fp) 将光标返回到开头
Tips:windows文本文件以\r\n为结尾,
linux和unix文本文件以\n结尾,
但是,读取时,windows下回自动将\r\n转为\n,如果是以二进制查看则没有这个转换
——————————————————————————————————————————————
删除、重命名文件
remove(pathname)
rename(oldpath, newpath)
成功时返回0
失败时返回-1
——————————————————————————————————————————————
文件缓冲区
int fflush(FILE *stream)
立即将缓冲区的数据写入到文件中
缓存 → 即当前操作的文件内容
更新到文件 → 将当前操作的内容写入到磁盘
程序编译
- 预处理
- 编译
- 汇编
- 连接
——————————————————————————————————————————————
来源:oschina
链接:https://my.oschina.net/LinearLawX/blog/3182835