第十章 利用文件保存数据
C文件的有关概念
什么是文件
C语言程序设计中,主要用到两种文件:
- 程序文件。包括.c文件、.obj文件、.exe文件等。这种文件是用来存放程序的,以便实现程序的功能。
- 数据文件。
文件一般指存储在外部介质上数据的集合。
将输入输出形象地称为流,即输入输出流。流表示了信息从源到目的端的流动。
输入输出数据流的开始和结束仅受程序控制而不受物理符号(如回车换行符)控制,这就增加了处理的灵活性。这种文件称为流式文件。
文件名
文件标识包括三部分:
- 文件路径
- 文件名主干
- 文件后缀
文件路径表示文件在外部存储设备中的位置。如:
文件的分类
根据数据的组织形式,数据文件可分为
- ASCII文件
- 二进制文件
ASCII文件又称文本文件,它的每一字节放一个字符的ASCII代码。
二进制文件是把内存中的数据按其在内存中的存储形式原样输出到磁盘上存放。
文件缓冲区
文件类型指针
- 缓冲文件系统中,关键的概念是文件类型指针,简称文件指针。
- 每个被使用的文件都在内存中开辟一个相应的文件信息区,用来存放文件的有关信息。
该结构体类型是由系统声明的,取名为FILE。
每一个FILE类型变量对应一个文件的信息区,其中包含该文件的有关信息。
-
定义以下FILE类型的变量
-
定义一个指向文件型数据的指针变量
文件的打开与关闭
对文件读写之前应该打开该文件,在使用结构之后应关闭该文件。
用fopen函数打开数据文件
调用方式通常为:
使用文件的方式
说明:
用fclose函数关闭文件
fclose函数调用的一般形式为:
fclose函数也带回一个值,当顺利地执行力关闭操作,则返回值为0;否则返回EOF(-1)
文件的顺序读取
向文件读写字符
对文本文件读入或输出一个字符的函数见表:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
int main() {
FILE* fp;
char ch, filename[10];
printf("请输入所用的文件名:");
scanf("%s", filename);
if ((fp = fopen(filename,"w")) == NULL)
{
printf("无法打开此文件\n");
exit(0);
}
ch = getchar();
printf("请输入一个准备存放到磁盘的字符串(以#结束):");
ch = getchar();
while (ch != '#')
{
fputc(ch,fp);
putchar(ch);
ch = getchar();
}
fclose(fp);
putchar(10);
return 0;
}
向文件读写一个字符串
读写一个字符串
说明:
例题:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main() {
FILE* fp;
char str[3][10], temp[10];
int n = 3;
printf("输出字符串:\n");
for (int i = 0; i < n; i++)
{
gets_s(str[i]);
}
for (int i = 0; i < n-1; i++)
{
int k = i;
for (int j = i+1; j < n; j++)
{
if (strcmp(str[k],str[j]) > 0)
{
k = j;
}
}
if (k != i)
{
strcpy(temp, str[i]);
strcpy(str[i], str[k]);
strcpy(str[k], temp);
}
}
if ((fp = fopen("file.dat","w")) == NULL)
{
printf("无法打开文件\n");
exit(0);
}
printf("\n新的序列为:\n");
for (int i = 0; i < n; i++)
{
fputs(str[i], fp);
fputs("\n", fp);
printf("%s\n", str[i]);
}
return 0;
}
文件的格式化读写
对文件进行格式化输入输出,这时就要用fprintf函数和fscanf函数。
一般调用方式为:
用二进制方式读写文件
C标准允许用fread函数从文件读一个数据块,用fwrite函数向文件写一个数据块。在进行读写时是以二进制形式进行的。在向磁盘写数据时,直接将内存中一组数据原封不动、不加转换地复制到磁盘文件上,在读入时也是将磁盘文件中若干字节的内容一批读入内存。
一般调用形式为:
例题
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#define SIZE 3
struct student_type
{
char name[10];
int num;
int age;
char addr[15];
}stud[SIZE];
void save() {
FILE* fp;
if ((fp = fopen("stu_dat","wb")) == NULL)
{
printf("无法打开文件!\n");
return;
}
for (int i = 0; i < SIZE; i++)
{
if (fwrite(&stud[i],sizeof(student_type),1,fp) != 1)
{
printf("文件写入错误!\n");
}
}
fclose(fp);
}
void load() {
FILE* fp;
if ((fp = fopen("stu_list", "rb")) == NULL)
{
printf("无法打开文件!\n");
return;
}
for (int i = 0; i < SIZE; i++)
{
if (fread(&stud[i], sizeof(student_type), 1, fp) != 1)
{
if (feof(fp))
{
fclose(fp);
return;
}
printf("文件读取错误");
}
}
fclose(fp);
}
int main() {
printf("输入学生信息:\n");
for (int i = 0; i < SIZE; i++)
{
scanf("%s%d%d%s", stud[i].name, &stud[i].num, &stud[i].age, stud[i].addr);
}
save();
return 0;
}
文件的随机读写
文件位置标记及其定位
-
文件位置标记
-
文件位置标记的定位
- 用rewind函数使文件位置标记指向文件头。如:rewind(fp1);
- 用fseek函数移动文件位置标记。
fseek函数的调用形式为:
-
用ftell函数测定文件位置标记的当前位置。
提高部分
系统定义的文件类型指针
回车换行符的转换
fread和fwrite函数用于二进制文件的输入输出
文件读写的出错检测
-
ferror函数
-
clearerr函数
小结