C总结-part_6-文件管理

C总结-part_6-文件管理

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
",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的结束时用
,getchar则是用来接收
,避免多次scanf导致问题;

// 更新缓冲区,比如说录入的时候终端了程序,原有的输入内容用fflush就会被缓存下来;
fflush(p); 

// 目标:使用命令 myvi ./a.txt 就可以对a.txt进行编辑

// 例、实现cat,即查看文本文件;
// cat ./a.txt  此时就会显示出文件的所有内容
// 例、四则运算
sprint(buf, "%d%c%d=
",a,b,c);
// 例如键入2*3=
,就会放入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个字符为作为字符的结束;
读取的数量可以超过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=
"的格式,提取各个变量值,赋值到abc当中
*/
sscanf(buf, "%d%c%d=
",&a,&b,&c);


/*
文件的格式化写入:将a b c value按照"%d%c%d=%.2f
"的格式组成字符串,存入到buf中
*/
fprintf(buf, "%d%c%d=%.2f
",a,b,c,value);

// 上面这句等价于
memset(buf,0,20);
sprintf(buf,"%d%c%d=%.2f
",a,b,c,value);
fputs(buf,fp2);

/*
文件的格式化读取
*/
fscanf(fp1, "%d+%d=%d
",&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文本文件以 为结尾,
linux和unix文本文件以 结尾,
但是,读取时,windows下回自动将 转为 ,如果是以二进制查看则没有这个转换


——————————————————————————————————————————————

删除、重命名文件

remove(pathname)
rename(oldpath, newpath)

成功时返回0
失败时返回-1

——————————————————————————————————————————————

文件缓冲区

int fflush(FILE *stream)
立即将缓冲区的数据写入到文件中

缓存 → 即当前操作的文件内容
更新到文件 → 将当前操作的内容写入到磁盘

程序编译

  • 预处理
  • 编译
  • 汇编
  • 连接

——————————————————————————————————————————————