网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
- fclose() —— 关闭文件;
- int fclose ( FILE * stream );
文件的使用方式:
按常用序:
使用方式 | 作用 | 如果文件不存在 |
“r”(只读) | 为了输入数据,打开一个已经存在的文本文件 | 出错 |
“w”(只写) | 为了输出数据,打开一个文本文件 | 建立一个新的文件 |
“a”(追加) | 向文本文件添加数据 | 建立一个新的文件 |
“rb”(只读) | 为了输入数据,打开一个二进制文件 | 出错 |
“wb”(只写) | 为了输出数据,打开一个二进制文件 | 建立一个新的文件 |
“ab”(追加) | 向一个二进制文件尾添加数据 | 出错 |
“r+”(读写) | 为了读和写,打开一个文本文件 | 出错 |
“w+”(读写) | 为了读和写,建立一个新的文本文件 | 建立一个新的文件 |
“a+”(读写) | 打开一个文本文件,在文件尾进行读写 | 建立一个文件 |
“rb+”(读写) | 为了读和写,打开一个二进制文件 | 出错 |
“wb+”(读写) | 为了读和写,建立一个新的二进制文件 | 建立一个新的文件 |
“ab+”(读写) | 打开一个二进制文件,在文件尾进行读写 | 建立一个新的文件 |
文件的顺序读写
函数名 | 功能 | 适用性 |
fgetc() | 字符输入函数 | 所有输入流 |
fputc() | 字符输出函数 | 所有输出流 |
fgets() | 文本行输入函数 | 所有输入流 |
fputs() | 文本行输出函数 | 所有输出流 |
fscanf() | 格式化输入函数 | 所有输入流 |
fprintf() | 格式化输出函数 | 所有输出流 |
fread() | 二进制输入 | 文件 |
fwrite() | 二进制输出 | 文件 |
以上结合起来实例:
#include<stdio.h>
#include<string.h>
#include<errno.h>
int main()
{
FILE* pf= fopen("test.txt", "w+");
if (pf == NULL)
{
printf("%s\n", strerror(errno));
return;
}
//输入一个字符
fputc('a', pf);
//用完关闭文件
fclose(pf);
pf = NULL;
return 0;
}
*如图示:*在源文件所在目录下,原本没有test.txt文件,是w+创建了这个新的文件,并写入一个字符a
1.写入一个字符:
//写文件
fputc('a', pf);
2.读取一个字符:
//读取一个字符
int ch = fgetc(pf);
if (ch != EOF)
{
printf("%c\n", ch);
}
3.连续每次读取一个字符:
//文件中有abcdefg
int ch = fgetc(pf);
printf("%c\n", ch); //a
ch = fgetc(pf);
printf("%c\n", ch); //b
ch = fgetc(pf);
printf("%c\n", ch); //c
ch = fgetc(pf);
printf("%c\n", ch); //d
4.覆盖并写入一行数据:
fputs("hello world", pf);
注意:这里fputs函数虽然是整行写入,但会覆盖掉原始数据、
5.读取指定长度的数据:
//定一一个数组
char arr[10] = { 0 };
fgets(arr, 5, pf); //将所读取的数据放入arr中
printf("%s\n", arr);
6.将结构体信息写入文件中:
这里的结构体信息就是格式化的,那么就需要fprintf()函数了
#include<stdio.h>
typedef struct S
{
char name[10];
int age;
}Peo;
int main()
{
FILE* pf = fopen("test.txt", "w");
if (pf != NULL)
{
Peo p = { "zhangsan", 18 };
fprintf(pf, "%s %d\n", p.name, p.age);
fclose(pf);
pf = NULL;
}
return 0;
}
7.读取文件信息到结构体变量中:
#include<stdio.h>
typedef struct S
{
char name[10];
int age;
}Peo;
int main()
{
FILE* pf = fopen("test.txt", "r");
if (pf != NULL)
{
Peo p = { 0 };
fscanf(pf, "%s %d", p.name, &p.age);
printf("%s %d", p.name, p.age);
fclose(pf);
pf = NULL;
}
return 0;
}
8.二进制写入文件:
- size_t fwrite( const void *buffer, size_t size**,** size_t count**,** FILE *****stream );
#include<stdio.h>
#include<string.h>
#include<errno.h>
typedef struct S
{
char name[10];
int age;
}Peo;
int main()
{
FILE* pf = fopen("test.txt", "wb+");
if (pf != NULL)
{
Peo p = { "lisi", 19};
fwrite(&p, sizeof(Peo), 1, pf);
fclose(pf);
pf = NULL;
}
return 0;
}
9.读取二进制文件信息:
- size_t fread( void *buffer, size_t size**,** size_t count**,** FILE *****stream );
#include<stdio.h>
typedef struct S
{
char name[10];
int age;
}Peo;
int main()
{
FILE* pf = fopen("test.txt", "rb+");
if (pf != NULL)
{
Peo p = { 0 };
fread(&p, sizeof(Peo), 1, pf);
printf("%s %d\n", p.name, p.age);
fclose(pf);
pf = NULL;
}
return 0;
}
10.sscanf()函数、sprintf()函数:
这两个函数虽然和文件操作关系不大,但是容易与文件操作函数混淆;
- sscanf()函数:
- int sscanf( const char *buffer, const char *format [, argument ] … );
- 将一个字符串转化为格式化数据;
#include<stdio.h>
typedef struct S
{
char name[10];
int age;
}Peo;
int main()
{
//定义一个字符串
char buffer[] = { "zhansan 19" };
//定义一个结构但不赋值
Peo p = { 0 };
sscanf(buffer, "%s %d", p.name, &p.age);
return 0;
}
- sprintf()函数:
- int sprintf( char *buffer, const char *format [, argument] … );
- 将一个格式化数据转化为字符串;
#include<stdio.h>
typedef struct S
{
char name[10];
int age;
}Peo;
int main()
{
//定义一个结构
Peo p = { "zhangsan",19};
//定义一个字符串
char buffer[50] = { 0 };
sprintf(buffer, "%s %d\n", p.name, p.age);
return 0;
}
文件的随机读写
所谓的随机读写,其实就是指定我们想要读写的位置。
fseek()函数:
- 该函数可以从定位位置的偏移量处开始读写;
- int fseek( FILE *stream, long offset, int origin );
文件流 偏移量 起始位置- 返回值:
- 如果成功,fseek返回0;
- 否则,它返回一个非零值;
- 在无法查找的设备上,返回值未定义;
三种定位指针:
使用实例:
#include<stdio.h>
#include<string.h>
#include<errno.h>
int main()
{
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
printf("%s\n", strerror(errno));
return;
}
//开始多次读取
//定位指针:比如要读取从头开始向后偏移 2 个单位的一个字符
fseek(pf, 2, SEEK_SET);
int ch = fgetc(pf);
printf("%c\n", ch);
//第二次读取:要拿到当前文件指针所处位置向后偏移5个单位的字符
fseek(pf, 5, SEEK_CUR);
ch = fgetc(pf);
printf("%c\n", ch);
//第三次读取:要拿到文件流末尾向前偏移8个单位的一个字符
fseek(pf, -8, SEEK_END);
ch = fgetc(pf);
printf("%c\n", ch);
fclose(pf);
pf = NULL;
return 0;
}
特别说明:
在每使用完一次fseek函数后,文件指针会自动向后移动一位:
ftell函数():
- 该函数可以返回文件指针相对于起始位置的偏移量;
- long int ftell ( FILE * stream );
使用实例:
我们直接在上一段代码的基础上加上ftell()函数即可直观得到每次文件指针所处的位置:
rewind()函数:
- 让文件指针回到文件初始位置;
- void rewind ( FILE * stream );
使用实例:
二进制文件和文本文件
我们知道数据在内存中是以二进制形式存储的,对于文件而言:如果不加转换直接输出到外存就是二进制文件;如果要在外存上以ASCII码形式存储,就需要提前转换最后以ASCII码值形式存储的文件就是文本文件。
对于字符,一律使用ASCII码形式存储,但对于数值型数据,即可以使用ASCII码存储也可以使用二进制形式存储。
举例:
数字10000的两种存储形式:
二进制文件:
文本文件:
首先将10000分成’1’,‘0’,‘0’,‘0’,‘0’, 这五个字符,用每个字符对应的ASCII码值进行转换:
由此可见:对于10000在数,如果以二进制形式存储占用4个字节,如果以ASCII码存储占用5个字节。试想:那对于数字1呢?
显而易见,二进制文件存储和文本文件存储对不同范围的数字可以做到节省空间。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
文本文件:
首先将10000分成’1’,‘0’,‘0’,‘0’,‘0’, 这五个字符,用每个字符对应的ASCII码值进行转换:
由此可见:对于10000在数,如果以二进制形式存储占用4个字节,如果以ASCII码存储占用5个字节。试想:那对于数字1呢?
显而易见,二进制文件存储和文本文件存储对不同范围的数字可以做到节省空间。
[外链图片转存中…(img-MBk0e9yE-1715601834376)]
[外链图片转存中…(img-JgWL5sa1-1715601834376)]
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!