c语言-文件
文件的基本知识
什么是文件
- 程序文件: 源程序文件(.c)、目标文件(.obj)、可执行文件(.exe)——即程序代码
- 数据文件:不是程序,而是供程序运行读写的数据——即数据
- 操作系统把各种设备都统一作为文件来处理
文件
一般是指存储再外部介质上数据的集合数据流
即数据的输入输出
文件名
- 文件路径
- 文件名主干
- 文件后缀
文件分类
- ASCII文件(文本文件) text file:每一个字节存放一个字符ASCII字
- 二进制文件(映像文件)image file:存储在内存的数据映像
- 如果要求在外存上以ASCII代码形式存储,则需要在存储前进行转换
- 字符一律ascii形式存储
- 数值型可以ascii或者二进制形式存储
比较:
- 二进制节省外存的空间和转换时间
- ASCII形式输出字节与字符一一对应,一个字节代表一个字符,便于输出字符;
- 但是一般占存储空间比较多,而且需要花费转换时间
文件缓冲区
ANSI C 采用”缓冲文件系统”处理文件
- 每个文件在内存中只有一个缓冲区
- 在向文件输出数据时,作为输出缓冲区
- 在向文件输入数据时,它作为输入缓冲区
文件类型指针
1 |
|
打开与关闭文件
fopen
1 |
|
Parameters
filename − This is the C string containing the name of the file to be opened.
mode − This is the C string containing a file access mode. It includes −
参数 | 作用 |
---|---|
r | 以只读方式打开文件,该文件必须存在。 |
r+ | 以读/写方式打开文件,该文件必须存在。 |
rb+ | 以读/写方式打开一个二进制文件,只允许读/写数据。 |
rt+ | 以读/写方式打开一个文本文件,允许读和写。 |
w | 打开只写文件,若文件存在则文件长度清为零,即该文件内容会消失;若文件不存在则创建该文件。 |
w+ | 打开可读/写文件,若文件存在则文件长度清为零,即该文件内容会消失;若文件不存在则创建该文件。 |
a | 以附加的方式打开只写文件。若文件不存在,则会创建该文件;如果文件存在,则写入的数据会被加到文件尾后,即文件原先的内容会被保留(EOF 符保留)。 |
a+ | 以附加方式打开可读/写的文件。若文件不存在,则会创建该文件,如果文件存在,则写入的数据会被加到文件尾后,即文件原先的内容会被保留(EOF符不保留)。 |
wb | 以只写方式打开或新建一个二进制文件,只允许写数据。 |
wb+ | 以读/写方式打开或新建一个二进制文件,允许读和写。 |
wt+ | 以读/写方式打开或新建一个文本文件,允许读和写。 |
at+ | 以读/写方式打开一个文本文件,允许读或在文本末追加数据。 |
ab+ | 以读/写方式打开一个二进制文件,允许读或在文件末追加数据。 |
- 函数的返回值:
则表示打开成功后的文件指针,格式为FILE类型,是一个结构体类型,供后面使用,如果打开失败,则返回NULL。
- 如果我们现在想打开一个D盘根目录下的abc.dat,并且想读出该文件里的数据,那么我们可以这样写
1 |
|
- 1. 该文件的目录是绝对路径,因此这样写,如果不写盘符比如abc.dat则表示相对路径,表示与本程序同目录下。
- 2. 路径中的反斜杠虽然只有一个,但这里打了两个,原因在于C语言字符串中对反斜杠要当作转义字符处理,因此要用两个反斜杠才能表示一个。
- 3. 一旦以r也就是只读的方式打开文件,后面则不允许写数据,否则会出错,一定要保持一致!
fclose
1 |
|
顺序读写文件
向文件读写字符
这里的数据以acsii码形式存储,即整型
fgetc
1 |
|
返回值: 读取成功时返回读取到的字符,读取到文件末尾或读取失败时返回EOF。
EOF 不绝对是 -1,也可以是其他负数,这要看编译器的实现。
1 |
|
- 在文件打开时,该指针总是指向文件的第一个字节。
- 使用 fgetc() 函数后,该指针会向后移动一个字节,所以可以连续多次使用 fgetc() 读取多个字符。
注意:这个文件内部的位置指针与C语言中的指针不是一回事。位置指针仅仅是一个标志,表示文件读写到的位置,也就是读写到第几个字节,它不表示地址。文件每读写一次,位置指针就会移动一次,它不需要你在程序中定义和赋值,而是由系统自动设置,对用户是隐藏的。
1 |
|
fputc
1 |
|
参数
char – 这是要被写入的字符。该字符以其对应的 int 值进行传递。
fp – 这是指向 FILE 对象的指针,该 FILE 对象标识了要被写入字符的流。返回值
如果没有发生错误,则返回被写入的字符。如果发生错误,则返回 EOF,并设置错误标识符。
1 |
|
- c语言中,已经在头文件中把fputc和fgetc函数定义为宏putc和getc
1 |
|
向文件读写字符串
fgets
文件 -- > 字符数组str
- 函数原型
1 |
|
fputs
字符数组\字符串常量\字符型指针 -- > 文件
1 |
|
格式化的方式读写文本文件
fscanf(文件指针,格式化字符串,输入表列)
1 |
|
fprintf(文件指针,格式化字符串,输出表列)
1 |
|
- fprintf和fscanf函数对磁盘读写
- 需要将ASCII码转化为二进制形式
- 再保存在内存变量中
- 输出时又要再把二进制形式转化为字符
- 花费时间较多
用二进制方式向文件读写一组数据
fread(buffer,size,count,fp)
fwrite(buffer,size,count,fp)
getw
putw
1 |
|
- buffer : 读入数据的存储区地址 / 以此地址开始的存储区
- size: 要读写的字节数
- count: 读入数据项个数(每个数据项长度为size)
- fp:FILE文件类型指针
打开文件时,指定使用二进制文件,则fread和fwrite就可以读写任何文件
1 |
|
对 EOF 的说明
EOF 本来表示文件末尾,意味着读取结束,但是很多函数在读取出错时也返回 EOF,那么当返回 EOF 时,到底是文件读取完毕了还是读取出错了?
- 我们可以借助 stdio.h 中的两个函数来判断,分别是 feof() 和 ferror()。
feof()
- 用于检测文件流是否到达了文件末尾(EOF),函数的原型如下:
1 |
|
参数
stream 是一个指向 FILE 类型的指针,表示要检查的文件流。返回值
如果文件流位于文件末尾,则该函数返回非零值。否则,返回零。注意
feof() 仅在尝试读取已到达文件尾之后的数据时才返回非零值,仅到达文件尾但未尝试读取的情况下,并不会导致 feof() 返回非零值。
1 |
|
ferror()
-ferror() 函数用来判断文件操作是否出错,它的原型是:
1 |
|
1 |
|
随机读写数据文件
- 随机访问:可以对任何位置上的数据进行访问
文件位置标记及其定位
文件位置标记 – 文件指针
一般情况(顺序读写):
- 对字符进行
顺序读写
,文件位置指向文件开头,文件位置标记会自动向后移动一个位置。 - 直到所有的数据写完,此时文件位置标记在最后一个数据之后。
- 对字符进行
随机读写
:- 人为地移动文件标记的位置。
流式文件即可以
随机读写
,又可以顺序读写
关键在于控制文件的位置标记
文件位置标记的定位
rewind函数
–使文件位置标记指向文件开头
1 |
|
fseek函数
– 改变文件位置标记
调用形式:
fseek(文件指针,位移量,起始点)1
int fseek ( FILE *fp, long offset, int origin );
参数说明:
fp 为文件指针,也就是被移动的文件。
offset 为偏移量,也就是要移动的字节数。之所以为 long 类型,是希望移动的范围更大,能处理的文件更大。offset 为正时,向后移动;offset 为负时,向前移动。
origin 为起始位置,也就是从何处开始计算偏移量。C语言规定的起始位置有三种,分别为文件开头、当前位置和文件末尾,每个位置都用对应的常量来表示:
起始点 常量名 常量值 文件开头 SEEK_SET 0 当前位置 SEEK_CUR 1 文件末尾 SEEK_END 2 例如,把位置指针移动到离文件开头100个字节处:
fseek(fp, 100L, 0);
值得说明的是,fseek() 一般用于二进制文件,在文本文件中由于要进行转换,计算的位置有时会出错。
ftell函数
– 测定文件位置标记的当前位置- 如果调用函数出错,返回-1L(fp文件指针不存在)
随机读写
1 |
|
1 |
|
文件读写出错检测
ferror
函数 – 错误流检查函数- 如果ferror 返回值为0 (假),表示未出错;如果返回一个非零值, 表示出错。
clearerr
函数 – 使文件错误标志和文件结束标志置为0- 假设在调用一个输入输出,函数时出现错误, ferror 函数值为一个非零值。应该立即涸用clearerr(fp) ,使ferror( fp ) 的值变成0 ,以便再进行下一次的检测。
- 只要出现文件读写出错标志,它就一直保留,直到对同一文件调用clearerr 函数或
rewind 函数. 或任何其他一个输入输出函数。