引入
前面,我们知道了什么是文件位置标记,以及如何控制文件位置标记,学会了 rewind 和 fseek 这两个函数后,我们就来实现一下随机读写!
例子
输入10个学生成绩,然后存储到文件,接着读入文件,将1,3,5,7,9号学生数据输出到计算机上。
1 |
|
高树靡阴,独木不林。
前面,我们知道了什么是文件位置标记,以及如何控制文件位置标记,学会了 rewind 和 fseek 这两个函数后,我们就来实现一下随机读写!
输入10个学生成绩,然后存储到文件,接着读入文件,将1,3,5,7,9号学生数据输出到计算机上。
1 | #include <stdio.h> |
我们之前讲的,都是对文件的顺序读写,很容易操作,但有时候效率不高。比如,文件中有1000个数据,我们如果需要找到第999号数据,那么需要从1遍历到998才可以。如果是一个城市几百万人的数据呢?所以随机访问应运而生,随机访问不是按数据在文件中的物理位置进行读写
,而是可以对任何位置上的数据进行访问
,显然这种方法比顺序访问高效
的多。
我们前面说过,w 方式打开是新建(有重名就删除再新建),文件标记在开头。a 方式打开是追加,文件标记在末尾。为了对读写进行控制
,系统位每个文件设置了一个文件读写位置标记
,简称(文件读写标记或文件标记),用来指示接下来要读写的下一个字符的位置
。
对文件进行读的操作
,然后文件位置标记向后移动一个位置
,如果再一次执行读操作,就会将位置2的字符读入,以此类推(我们前面的例子也说过)直到文件尾。
前面我们说,使用 fprintf 和 fscanf 确实很方便,也很好理解,但是频繁的进行读写,二进制和 ASCII 码转来转去不是事,太耽误时间了,那么今天我们就来学习如何读取和写入二进制数据,还能一次输入输出结构体等成组的数据哦~
一般形式
fread (buffer,size,count,fp);
fwrite(buffer,size,count,fp);
参数说明
我知道这里的 buffer、size 和 count 把大家绕晕了,我再来说明一下
1 | float f[20]; |
我们前面将了如何输出一个字符、如何输出一串字符,但是数据并不仅仅只有字符,数据的类型是十分丰富的。我们在使用 printf 和 scanf 的时候,通过%d %s %f %o
来格式化不同的数据,那么磁盘文件能否也这样进行操作呢?
其实就像 gets 、puts 和 fgets、fputs一样。
格式化读写函数是从 printf 、scanf 延伸
fprintf(文件指针,格式字符串,输出表列);
fscanf(文件指针,格式字符串,输入表列);
fprintf 函数:
1 | int i=3; |
前面我们学习了如何向文件写入一个字符,以及读取一个字符串,但是这太反常识了,有没有方便读写一个字符串的方法呢?当然是有的!😎
C 语言允许通过函数 fgets 和 fputs 一次读写一个字符串
函数名 | 调用形式 | 功能 | 返回值 |
---|---|---|---|
fgets | fgets(str,n,fp) | 从 fp 指向的文件中,读取一个长度位 n-1 的字符串,存放到字符数组 str 中。 | 成功则返回str 的地址,失败则返回 NULL |
fputs | fputs(str,fp) | 把 str 所指向的字符串写到文件指针变量 fp 中 | 成功为0,失败为非0 |
一般形式
char fgets (char str , int n , FILE *fp);
作用是从文件读入一个字符串到字符数组
1 | fgets(str, n, fp); |
前面,我们学会了如何打开一个文件,并创建一个指针指向该文件。打开之后,我们就要对文件进行读写了。
对文件进行读写一个字符,需要下面这两个函数
函数名 | 调用形式 | 功能 | 返回值 |
---|---|---|---|
fgetc | fgetc(fp) | 从 fp 指向的文件读入一个字符 | 读入成功,返回所读的字符 读入失败,返回-1 |
fputc | fputc(fp) | 把字符 ch 写到文件指针变量 fp 指向的文件 | 输出成功,返回输出的字符 输出失败,返回-1 |
fgetc 中
从键盘逐个输入字符串,然后用 fputc 函数写到磁盘文件中
1 | #include <stdio.h> |
我们讲了这么久的文件,知道了文件名、内存缓冲区、缓冲区中的文件信息区以及定义一个 FILE 结构体变量和指针。今天我们就来尝试打开和关闭一个文件。
ANSI C 规定了用标准输入输出函数 fopen 来实现打开文件
一般形式
fopen (文件名 , 使用文件方式);
例如:
1 | fopen("a1","r"); |
a1:是要打开的文件名,也可以是字符数组的首地址
r:使用文件方式(r 表示 read 读入)
fopen 函数的返回值是指向 a1 文件的指针
,也就是 a1 在内存中的文件信息区的起始地址
。所以,我们经常将 fopen 函数的返回值给一个指向文件的指针变量。
1 | FILE *fp; //定一个指向文件的指针变量 fp |
在上节讲的缓冲文件系统中,最关键的概念就是文件类型指针
,简称为:文件指针
。我们知道,要让程序操作一个文件,都需要将其加载到内存中,但是加载到内存之前,需要现经过缓冲区。所以,每个文件被使用时,都在内存中开辟一个相应的文件信息区,用来存放文件的有关信息。
有关信息包括:文件名、文件状态及文件当前位置等信息
这些信息都是保存在一个结构体变量中的,该结构体类型由系统声明,取名为FILE
。
在不同的 C 编译环境中 FILE 的内容可能不完全相同,我们来举个例子,FLIE 的结构体可能是这样的,它包含在stdio.h
中:
1 | typedef struct { |
根据数据的组织形式不同,数据文件可以分为:
数据在内存中是以二进制
形式存储的。
如果不加转换,输出到外存,就是二进制文件
,
可以认为它是存储在内存的数据的影响,也称之为映像文件
。
如果要求在外存上以 ASCII 码的形式存储,需要在存储前将二进制文件转换成 ASCII 文件
,又称文本文件
,每一个字节存放一个字符的 ASKII 码。
字符:一律以 ASCII 码形式存储。
数值:即可以以 ASCII 码形式存储,也可以以二进制存储。
存储整数 10000
ASKII 码:5个字节(每个字符占 1 字节)
二进制:4个字节
只要是会使用计算机的人,对文件
一定都不陌生,word 文件、PPT 文件、邮件的附件、照片、视频都是文件。要在程序中操作这些文件,就需要对文件的基础进行了解。
文件有不同的类型,在程序设计中,主要用到两种文件
.c文件
、目标文件.obj文件
以及可执行文件.exe 文件
等。这种文件的内容是程序代码。程序运行时读写的数据
。包括在程序运行过程中输出到磁盘的数据、供程序读入的数据。如成绩数据或者货物交易记录等
。本章我们主要讨论的是第二种,数据文件。