文件基本概念
-
文件分类
-
文本文件
- 以ASCII码格式存放,一个字节存放一个字符.
-
二进制文件
- 以二进制存储的
-
-
文本文件和二进制文件的区别
- 1.存储步骤不同
- 文本文件在存储的时候,会先查询需要存储数据的ASCII码, 然后再将对应的ASCII 码转换为二进制,然后再存储;
- 2.从存储步骤来看,文本文件需要县查找再存储, 所以效率会低一些
- 3.从内存上的表现, 文本文件会更占用内存
- 1.存储步骤不同
- 注意点:
- 任何的文本编辑器在打开文件的时候,都会以某种编码方式去解码存储的数据
- 而文本编辑器默认的解码方式就是ASCII码解码
文件的打开和关闭
- fputc/ fputs/ fgetc/ fgets 这些函数都是用于操作文本文件的;
- fwrite / fread 这两个函数就是用于操作二进制文件的
- 也就是说:
- fputc/ fputs/ fgetc/ fgets保存的都是 ASCII码
- fwrite / fread 保存的是二进制
fopen()函数
- fopen函数返回的FILE * 是一个指向结构体的指针;
- FILE *并不是打开的那个文件, 而是一个结构体,这个结构体中描述了被打开文件在缓冲区中的各种状态
- 函数的声明: FILE * fopen ( const char * filename, const char * mode );
- 两个参数都是传入字符串
- 第一个参数: 需要打开的文件的名称
- 第二个参数: 打开文件的模式
- 返回值: 如果打开文件成功, 会返回文件的句柄, 如果打开失败会返回NULL
- 模式的对应取值
- r 读取文件
- 文件不存在会报错,文件存在就打开
- 只能读不能写
FILE *fp = fopen("abc.txt", "r"); if(fp == NULL){ printf("打开失败\n"); }
- w 写入文件
- 文件不存在会自动创建, 文件存在会直接打开
- 只能写不能读
FILE *fp = fopen("abc", "r"); if(fp == NULL){ printf("打开失败"); }
- r+ 读取和写入文件
- 文件不存在会报错,文件存在就会打开
- 既可以读又可以写
FILE *fp = fopen("abc.txt", "r+"); if(fp == NULL){ printf("打开失败"); }
- w+ 读取和写入文件(重点)
- 文件不存在会自动创建, 文件存在会直接打开
- 既可以读也可以写
FILE *fp = fopen("abc.txt", "w+"); if(fp == NULL){ printf("打开失败\n"); }
- a 追加写入文件
- 文件不存在会自动创建, 文件存储会直接打开
- 只能在原有数据的基础上追加
FILE *fp = fopen("abc.txt", "a"); if(fp == NULL){ printf("打开失败\n"); }
- a+ 追加写入文件,并且可以读取(重点)
- 文件不存在会自动创建, 文件存在会直接打开
- 可以在原有数据的基础上追加, 并且还可以读取数据
FILE *fp = fopen("abc.txt", "a+"); if(fp == NULL){ printf("打开失败\n"); }
fclose()函数
- 格式: fclose(fp);
- 第一个参数: 需要关闭的文件句柄
- 返回值: int 成功返回0, 失败返回 EOF(-1);
- 一次写入一个字符 (fputc函数)
- fputc就是写入一个字符
- fputc是以文本文件的形式保存数据
- 格式: int fputc (int ch, FILE * stream );
- 第一个参数: 需要写入到文件的字符
- 第二个参数: 已经打开文件句柄;
- 返回值:写入成功,返回写入成功的字符, 如果失败, 返回 EOF
- EOF 是文件结束的标识,本质上就是-1;
FILE *fp = fopen("abc.txt", "w"); int res = fputc('a', fp); printf("res = %i\n", res); // 关闭打开的文件 fclose(fp);
一次读取一个字符(fgetc()函数)
- int fgetc ( FILE * stream );
- 第一个参数: 被读取的文件的 文件句柄
- 返回值:当前获取到的字符, 如果获取失败就会返回 EOF
FILE *fp = fopen("abc.txt", "w+"); fputc('a',fp); fputc('b',fp); fputc('c',fp); fputc('d',fp); // 每次操作完文件,文件的指针都会向后移动 // 将文件指针重新只想一个流的开头 rewind(fp); // fgetc 被读取的文件的 文件句柄 char ch ; while((ch = fgetc(fp)) != EOF){ printf("ch = %c\n", ch); }
文件末尾的判断(feof()函数)
-
feof()函数(了解一下)
- 返回值为0, 没有读到文件末尾
- 如果返回非0, 代表读到了文件末尾
#include <stdio.h> int main() { FILE *fp = fopen("abc.txt", "w+"); fputc('a',fp); fputc('b',fp); fputc('c',fp); fputc('d',fp); // 将文件指针重新只想一个流的开头 rewind(fp); // 按照下列的写法, 会多读取一个字符 // 原因就是feof函数在判断文件指针时, 指针还没有移动 // 只有写入或者读取过来指针才会移动 char ch ; // while(!feof(fp)){ // ch = fgetc(fp); // printf("ch = %c\n", ch); // } // 所以在使用feof函数的时候, 一定要先取, 然后再判断feof // 否者会多取一个 while((ch = fgetc(fp)) && !feof(fp)){ printf("ch = %c\n", ch); } return 0; }
-
注意点:在使用feof函数的时候,一定要先取 ,然后再判断Feof, 否则会夺取一个
-
定义函数, 实现文件的加密和解码
#include <stdio.h>
void encode(char *name, char *newName, int code);
int main()
{
// 编码
//encode("abc.txt", "encode.txt", 6);
// 解码
encode("encode.txt", "decode.txt", 6);
return 0;
}
void encode(char *name, char *newName, int code){
// 打开一个需要加密的文件
FILE *fr = fopen(name, "r+");
// 打开需要写入加密内容的文件
FILE *fw = fopen(newName, "w+");
// 不断的读 不断的加密 不断的写入
char ch = EOF;
while((ch = fgetc(fr)) != EOF){
ch = ch ^ code;
fputc(ch, fw);
}
// 关闭已经打开的文件
fclose(fr);
fclose(fw);
}
一次性写入一行数据(fputs()函数)
- fputs()函数可以一次写入一堆字符
- 格式: fputs(const char * restrict _Str,FILE * restrict _File);
- 第一个参数: 需要写入的数据
- 第二个参数: 写入到那个文件的文件句柄
- 注意点: 不会再写入字符的后面自动添加\n
// 打开一个文件
FILE *fp = fopen("abc.txt", "w+");
// 一次写入一堆函数:需要自己添加换行 \n
fputs("www.baidu.com\n", fp);
fputs("www.taobao.com\n", fp);
// 关闭打开的文件
fclose(fp);
一次性读取一行数据(fgets()函数)
-
fgets()函数 格式: fgets(char * restrict _Buf,int _MaxCount,FILE * restrict _File);
- 第一个参数: 读取出来的数据会放到这个参数的变量中
- 第二个参数: 需要读取多少个字节的数据
- 第三个参数: 被读取文件的句柄
- 注意点: 虽然告诉系统需要读取1024个字符,但是只要遇到\n, fgets函数就会自动终止读取
FILE *fp = fopen("abc.txt", "r+"); char buf[1024]; fgets(buf, 1024, fp); printf("buf = %s\n", buf); // 关闭打开的文件 fclose(fp);
-
注意点:
- 遇到\n自动结束,并且\n 也会被读取进来
- maxCount 指定多睡不一定会读取多少, 读取到\n会自动停止读取
- 最多只能读取 maxCount - 1 个字符, 会在最后自动添加 \0
- 遇到EOF也会自动停止读取
#include <stdio.h> int main() { FILE *fp = fopen("abc.txt", "r+"); char buf[1024]; /* * abc.txt : hello world * www.baidu.com */ // 每次只能读取n-1个字符, 会在末尾自动添加\0 fgets(buf, 4, fp); printf("buf = %s\n", buf); // hel fgets(buf, 1024, fp); printf("buf = %s\n", buf); // 关闭打开的文件 fclose(fp); return 0; }
-
遍历写法
// 推荐写法
while(fgets(buf, 1024, fp) != NULL){
printf("buf = %s\n", buf);
}
// 不推荐写法
while(fgets(buf, 1024, fp) && !feof(fp)){
printf("buf = %s\n", buf);
}
一次性写入一块数据(fwrite()函数)
- 格式: fwrite(const void * restrict _Str,size_t _Size,size_t _Count,FILE * restrict _File);
- 第一个参数: 需要写入文件的数据地址
- 第二个参数: 每次写入多少个字节
- 第三个参数: 需要写入多少次
- 第四个参数: 写入到上面地方
- 返回值: 写入了多少次就返回多少, 出错或文件结束, 返回 0;
FILE *fp = fopen("abc.txt", "w+");
int ages[] = {1, 3, 5};
printf("sizeof(ages) = %i\n", sizeof(ages));
fwrite(&ages, sizeof(ages), 1, fp);
- 注意点:
- 一般情况下, 写入一块数据,每次写入多少个字节可以写大一点, 而写入多少次会写小一点;
- 由于fwrite是以二进制的形式写入文件的, 所以和以文件的写入不同, fwrite函数会忽略 \0 \n等内容;
FILE *fp = fopen("abc.txt", "w+");
char *str = "hello\0world";
// fputs是以文本文件的形式存储, 存储的是ASCII
// 注意点: 如果利用fputs写入字符串, 遇到\0会停止写入
// fputs(str, fp);
// 注意点: 在二进制中是没有\n \0这些概念的, 写入的时候不会受到\0 \n的影响
fwrite(str, 9, 1, fp);
一次性读取一块数据(fread()函数)
- 格式: fread(void * restrict _DstBuf,size_t _ElementSize,size_t _Count,FILE * restrict _File);
- 第一个参数: 读取的数据存储到哪
- 第二个参数: 一次读取多少个字节
- 第三个参数: 读取多少次
- 第四个参数: 从什么地方读取
- 返回值: 读取了多少就返回多少, 如果返回0 代表读取错误
FILE *fp = fopen("abc.txt", "w+");
// abc.txt : hello world
char buf[1024] = {0};
// fp对应的文件中读取1024次,每次读取1个字节, 将读取的内容放到buf中
fread(buf, 1, 1024, fp);
printf("buf = %s\n", buf);
- 注意点:
- fread(buf, 1, 1024, fp); 虽然告诉系统需要读取1024次,但是只要读取到EOF就不会读取了
- 每次读取多少个字节, 一定要按照存储的数据类型占用的内存大小来读取, 不要写过大的值
FILE *fp = fopen("abc.txt", "wb+");
char *str1 = "123456";
fwrite(str1, sizeof(char), strlen(str1), fp);
rewind(fp);
char buf[1024] = {0};
while(fread(buf, 1, 1024, fp) > 0){
printf("buf = %s\n", buf);
}
读写结构体
- 读单个结构体
#include <stdio.h>
typedef struct person{
char *name;
int age;
double height;
} Person;
int main()
{
// // 写入一个结构体
// Person p = {"www", 18, 1.78};
// FILE *fp = fopen("abc.txt", "wb+");
// fwrite(&p, sizeof(Person), 1, fp);
// // 关闭文件
// fclose(fp);
// 读一个结构体
FILE *fp = fopen("abc.txt", "rb+");
Person p;
fread(&p, sizeof(Person), 1, fp);
printf("name = %s\n", p.name);
printf("age = %i\n", p.age);
printf("height = %lf\n", p.height);
// 关闭文件
fclose(fp);
return 0;
}
- 读写结构体数组
#include <stdio.h>
typedef struct person{
char name[8];
int age;
double height;
} Person;
int main()
{
// // 写入一个结构体数组
// Person ps[3] = {
// {"www", 38, 1.38},
// {"baidu", 18, 1.78},
// {"com", 98, 1.58},
// };
// FILE *fp = fopen("abc.txt", "wb+");
// fwrite(&ps, sizeof(ps), 1, fp);
// // 关闭文件
// fclose(fp);
// 读一个结构体数组
FILE *fp = fopen("abc.txt", "rb+");
Person ps[3];
fread(&ps, sizeof(Person), 3, fp);
for(int i = 0; i< 3; i++){
Person p = ps[i];
printf("name = %s\n", p.name);
printf("age = %i\n", p.age);
printf("height = %lf\n", p.height);
printf("----------\n");
}
// 关闭文件
fclose(fp);
return 0;
}
网友评论