C文件操作2:如何随机的进行文件读取?
上篇介绍了C语言文件操作的基本函数,fopen、fwrite、fread、fclose。这些只能从文件头读写或文件尾追加写入。
本篇介绍文件中随机位置读写的方法,会介绍fseek、ftell、rewind。
此外,再介绍几个字符读写函数:fputs、fgets、fpritf、fscanf,用于编写测试代码时用。
文件随机位置读写基础函数
对于文件的随机位置读写,可以通过 fseek 、ftell与rewind 函数来完成
fseek
fseek用于设置流stream的文件读写位置为给定的偏移
seeK的中文含义是“寻找”
函数原型:
1 | /** @func: fseek |
from参数的取值
起始点 | 表示 符号 | 数字表示 |
---|---|---|
文件开头 | SEEK_SET | 0 |
当前位置 | SEEK_CUR | 1 |
文件末尾 | SEEK_END | 2 |
例如:
- 将读写位置移动到文件开头
1 | fseek(fp, 0L, SEEK_SET) |
- 将读写位置移动到文件末尾
1 | fseek(fp,0L,SEEK_END); |
- 将读写位置移动到离文件开头100字节处
1 | fseek(fp,100L,SEEK_SET); |
- 将读写位置移动到离文件当前位置100字节处
1 | fseek(fp,100L,SEEK_CUR); |
- 将读写位置退回到离文件结尾100字节处(offset为负数表示向开头处移动)
1 | fseek(fp,-100L,SEEK_END); |
注意:
fseek 函数一般用于二进制文件,当然也可以用于文本文件。
当fseek函数操作文本文件时,要注意回车换行的情况。
因为在一般浏览工具(如 UltraEdit)中,回车换行被视为两个字符 0x0D 和 0x0A,但真实的文件读写和定位却按照一个字符 0x0A 进行处理。
这种清空,可以先将文件整个读入内存,然后在内存中手工插入 0x0D。
ftell
fseek 函数只返回执行的结果是否成功,并不返回文件的读写位置
获取当前文件的读写位置,还需要使用 ftell 函数来获取
函数原型:
1 | /** @func: ftell |
fell的主要作用就是获取当前的读写位置,在随机方式存取文件时,由于文件位置频繁前后移动,程序不容易确定文件的当前位置。
在使用 fseek 函数移动了位置后,再调用函数 ftell 就能非常容易地确定文件的当前位置。
fell的一个小应用:获取文件的长度
加入一共文件的读写位置已经被移动了多次,这时若想获得文件的长度,可以向用ftell记录当前的读写位置,然后将其移动到末尾,再利用ftell获取文件尾至头部的位置,就是文件的长度了。获取程度之后,再将读写位置使用fseek复原即可。
1 | long getFileLength(FILE *fp) |
代码对应的设计思路如下图:
rewind
rewind的中文意思是“倒回”
rewind 函数用于将文件内部的位置指针重新指向一个流(数据流或者文件)的起始位置。
注意,这里的“指针”表示的不是文件指针,而是文件内部的位置指针。即随着对文件的读写,文件的位置指针(指向当前读写字节)向后移动。而文件指针指向整个文件,如果不重新赋值,文件指针不会发生改变。
函数原型:
1 | /** @func: rewind |
由于 rewind 函数没有返回值,所以很难判断
rewind(fp)
是否执行成功。因此,应该尽量使用 fseek 来替换 rewind 函数,从而以验证流已经成功地回绕
文件读取写入字符串
fputs
fputs函数用于将一行字符串写入文件
函数原型:
1 | /** @func: fputs |
fgets
fgets 函数用来从指定的文件中读取一个字符串,并保存到字符数组中
函数原型:
1 | /** @func: fgets |
fprintf
函数原型:
1 | /** @func: fprintf |
使用方法:
1 | FILE *fp = fopen ("test.txt", "w+"); |
fscanf
函数原型:
1 | /** @func: fscanf |
使用方法:
1 | FILE *fp = fopen ("test.txt", "r"); |
使用示例
下面的测试程序,首先使用fputs函数写入了一段字符串“Hello world”,然后使用fseek函数,将读写位置移动到了文件开头向后的第6个字符,接着在该处,又使用fputs函数写入了一段字符串“xxpcb.github.io”,这样,就会在指定位置处,进行覆盖写入。最后,使用fgets函数,将文件中写入的内容再获取出来。
1 |
|
代码对应的设计思路如下图:
附:本篇以及上篇的测试代码,可从我的gitee仓库获取(地址:https://gitee.com/xxpcb/c-test/tree/master/C-file-operate),或公众号后台回复“**C文件操作**”获取~