文件操作
推荐一款超级好用的面试题复习工具:牛客网,涵盖了各个领域的面试题库,还有各大厂商的真题!
有各种语言的编程题,很多公司都用这个网站参加笔试。 快来研究问题吧! ! !
1. 文件的使用
之前的通讯录,如果每次运行完之后再次启动,就会发现上次的数据全部消失了,每次都要重新输入。 使用文件,我们可以将数据直接存储在计算机的硬盘上,实现数据的持久化。
2. 打开和关闭文件 2.1 文件指针
每个使用过的文件都会在内存中开辟一个对应的文件信息区域,用于存储文件相关信息(如文件名、文件状态和文件当前位置等)。 该信息存储在结构变量中。 结构体类型由系统声明并命名为FILE。 当我们打开文件时,系统会自己创建结构体变量。 我们可以使用FILE指针来维护结构体变量。
2.2 打开和关闭文件
在读取或写入之前应打开文件,在使用后应关闭文件。
这有点像动态内存中的内存泄漏问题。 您不能只打开文件而不关闭它。
//打开文件
FILE * fopen ( const char * filename, const char * mode );
//关闭文件
int fclose ( FILE * stream );
2.3 文件的打开方式及顺序读写
打开方法:
“r”(只读)打开一个文本文件以供输入
“w”(只写)打开一个文本文件进行输出
“a”(追加)将数据添加到文件末尾
“rb”(只读)打开一个二进制文件用于输入
“wb”(只写)打开二进制文件进行输出
“r+”(读写)打开文本文件进行读写
“w+”(读写)创建一个新的文本文件用于读写
“a+”(读写)打开文本文件进行读写
“rb+”(读写)打开二进制文件进行读写
“wb+”(读写)创建一个新的二进制文件用于读写
“ab+”(读写)打开二进制文件进行读写
文件顺序读写:
我们在目录下创建文本文档text.txt来验证:
2.3.1 fputc
int fputc( int c, FILE *stream );
写一个字符。
int c 表示的公式的 ASCII 值。
int main()
{
FILE* pf = fopen("text.txt", "w");
if (pf == NULL)
{
printf("%s\n", strerror(errno));
return 1;
}
char i = 'a';
for (i = 'a'; i < 'z'; i++)
{
fputc(i, pf);
}
//关闭
fclose(pf);
pf = NULL;
return 0;
}
运行后查看txt文档:
2.3.2 fgetc
int fgetc( FILE *stream );
读一个字符。
int main()
{
FILE* pf = fopen("text.txt", "r");
if (pf == NULL)
{
printf("%s\n", strerror(errno));
return 1;
}
int ch;
while ((ch = fgetc(pf)) != EOF)
{
printf("%c ", ch);
}
//关闭
fclose(pf);
pf = NULL;
return 0;
}
2.3.3 输出量
int fputs( const char *string, FILE *stream );
写一行字符。
int main()
{
FILE* pf = fopen("text.txt", "w");
if (pf == NULL)
{
printf("%s\n", strerror(errno));
return 1;
}
fputs("hello", pf);
//关闭
fclose(pf);
pf = NULL;
return 0;
}
有些人可能会有疑问,前面写的代码去了哪里:
当我们使用“w”时,它会自动清除然后写入。
如果使用“a”,则附加它:
FILE* pf = fopen("text.txt", "a");
2.3.4 fgets
char *fgets( char *string, int n, FILE *stream );
读取成功时返回,失败或到达文件末尾时返回NULL。
读取一行数据。
int main()
{
FILE* pf = fopen("text.txt", "r");
if (pf == NULL)
{
printf("%s\n", strerror(errno));
return 1;
}
char arr[20];
fgets(arr, 5, pf);
printf(arr);
//关闭
fclose(pf);
pf = NULL;
return 0;
}
可以看到这里只读取了四个字符。 原来这里的5包含'\0'。
2.3.5
int fprintf( FILE *stream, const char *format [, argument ]...);
格式化并写入(文件)数据。
struct A
{
char a[10];
int b;
};
int main()
{
struct A a = { "abcdef", 20 };
FILE* pf = fopen("text.txt", "w");
if (pf == NULL)
{
printf("%s\n", strerror(errno));
return 1;
}
fprintf(pf, "%s %d", a.a, a.b);
//关闭
fclose(pf);
pf = NULL;
return 0;
}
运行后结果:
2.3.6
int fscanf( FILE *stream, const char *format [, argument ]... );
格式化读取(文件)数据。
struct A
{
char a[10];
int b;
};
int main()
{
struct A a = { 0 };
FILE* pf = fopen("text.txt", "r");
if (pf == NULL)
{
printf("%s\n", strerror(errno));
return 1;
}
fscanf(pf, "%s %d", a.a, &a.b);
printf("%s %d", a.a, a.b);
//fprintf(stdout, "%s %d", a.a, a.b);
//关闭
fclose(pf);
pf = NULL;
return 0;
}
运行后结果:
2.3.7
size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream );
以二进制形式编写(必须是文件)。
因为你想将二进制写入文件,所以它是“wb”。
struct A
{
char a[10];
int b;
};
int main()
{
struct A a = { "abcdef", 20 };
FILE* pf = fopen("text.txt", "wb");
if (pf == NULL)
{
printf("%s\n", strerror(errno));
return 1;
}
//以二进制写
fwrite(&a, sizeof(struct A), 1, pf);
//关闭
fclose(pf);
pf = NULL;
return 0;
}
运行后结果:
有一些二进制代码我们看不懂,但是我们可以用函数把它们读出来:
2.3.8 恐惧
size_t fread( void *buffer, size_t size, size_t count, FILE *stream );
读取二进制文件(必须是文件)。
struct A
{
char a[10];
int b;
};
int main()
{
struct A a = { "abcdef", 20 };
FILE* pf = fopen("text.txt", "rb");
if (pf == NULL)
{
printf("%s\n", strerror(errno));
return 1;
}
//以二进制读
fread(&a, sizeof(struct A), 1, pf);
printf("%s %d", a.a, a.b);
//关闭
fclose(pf);
pf = NULL;
return 0;
}
运行后结果:
2.4 比较一组函数
扫描//
//
scanf是标准输入的格式化输入语句
是标准输出的格式化输出语句
是所有标准输入流的格式化输入语句
是所有标准输出流的格式化输出语句
:
将格式化数据转换为字符串。
:
从字符串转换为格式化数据。
struct A
{
char a[10];
int b;
};
int main()
{
struct A a = { "abcdef", 20 };
struct A tmp = { 0 };
char buf[100] = {0};
//把s中的格式化数据转化成字符串放入buf中
sprintf(buf, "%s %d", a.a, a.b);
//从字符串buf中获取格式化数据到tmp中
sscanf(buf, "%s %d", tmp.a, &tmp.b);
return 0;
}
3.随机读写 3.1 fseek
根据文件指针的位置和偏移量定位文件指针。
int fseek( FILE *stream, long offset, int origin );
当我们文件中的内容为:“”时,用fgetc()读取时,如果要读取f,只能从a开始往后读取。 这时候就可以使用fseek来解决这个问题。
fseek 的三个起始位置:
文件开头