C基础——文件I/O(2)
## 1、fprintf()、fscanf()和rewind()
```C
int fprintf(FILE*, const char* format, [待打印项...]);
```
第1个参数通过文件指针指定输出位置;第2个参数是格式化字符串;第3个参数可选
```C
int fscanf(FILE*, const char* format, 待输入项的地址);
```
```C
void rewind(FILE*);
```
rewind()接收文件指针,使程序返回到文件的起始位置
## 2、随机访问:fseek()和ftell()
```C
int fseek(FILE*, long, int);
```
第1个参数指向已经被fopen()打开的待查找的文件;
第2个参数是***偏移量***,表示从起始位置开始要移动的距离,必须是long类型的值,相对于当前位置,正值为向后偏移,负值为向前偏移,0表示不移动
第3个参数是模式,确定起始位置,定义在stdio.h中
|模式|偏移量的起始位置|
|-|-|
|SEEK_SET|文件开始处|
|SEEK_CUR|当前位置|
|SEEK_END|文件末尾|
----
旧的实现可能缺少这些宏定义,可以使用数值0L、1L、2L分别表示这3种模式
----
如果正常,fseek()返回值为0,如果出现错误,返回值为-1
```C
long ftell(FILE*);
```
接收一个文件指针,返回值是long类型,返回文件指针的***当前位置***距离文件***起始位置***的***字节数***,文件的第1个字节与起始位置的距离为0,
ANSI C规定,此定义只适用于以二进制模式打开的文件
```C
#include
int main(void)
{
FILE* fp;
char ch;
fp = fopen("mytest", "w+");
fprintf(fp, "abcdefg");
fseek(fp, 0L, SEEK_SET); //将fp定位至文件开头
ch = getc(fp);
printf("%c\n",ch); // ch = 'a';
fseek(fp, 1L, SEEK_SET); //将fp从文件开头向后偏移一个字节
ch = getc(fp);
printf("%c\n",ch); // ch = 'b';
fseek(fp, 0L, SEEK_CUR); //将fp定位至当前位置
ch = getc(fp);
printf("%c\n",ch); // ch = 'c';
printf("%ld\n", ftell(fp)); // 输出结果为 3,即,fp距离文件开头3个字节
return 0;
}
```
## 3、二进制模式与文本模式
对于UNIX系统,只有一种文件格式,所以不需要进行特殊的转换。
对于其它系统,二进制模式的文件读写可能与文本模式有所不同,所以在读写时要注意两者之间的区别。
例如,在MS_DOS中,编辑器以CTRL+Z标记文本文件的结尾。当以文本模式打开这些文件的时候,C可以识别这个文件结尾标记。但是,在以二进制模式打开这些文件时,CTRL+Z被当做是可以打印的字符,而真正的文件结尾标记在该字符的后面。
此外,在MS_DOS中,使用\r\n组合来表示文本文件的换行符。以文本模式打开这些文件,C会将\r\n自动转换为\n。但以二进制模式打开这些文件时,程序看到的就是\r\n,不会进行转换。
ftell函数在文本模式和二进制模式中的工作方式不同。
### 4、可移植性
为了确保可移植性,ANSI C有以下规定
***第一***,在二进制模式中,实现不必支持SEEK_END模式。替代方法是,从文件开始处逐个字符读取文件直到文件结尾。C预处理器的条件编译指令提供了一种系统方法来处理这种情况
***第二***,在文本模式中,只保证以下行为
|函数调用|效果|
|-|-|
|fseek(file, 0L, SEEK_SET)|将文件指针定位至文件开始处|
|fseek(file, 0L, SEEK_CUR)|将文件指针定位至当前位置|
|fseek(file, 0L, SEEK_END)|将文件指针定位至文件结尾|
|fseek(file, ftell-pos, SEEK_SET)|将文件指针定位至,到距离文件开始处ftell-pos的位置。ftell-pos是ftell()的返回值|
## 5、fgetpos()和fsetpos()函数
```C
int fgetpos(FILE* restrict stream, fpos_t* restrict pos);
```
fpos_t(file position type):文件定位类型,可以根据除数组以外的他类型来定义,在文件中指定一个位置
函数功能:接收一个文件指针,并将文件指针当前位置距离文件起始位置偏移的字节数存入pos指向的对象
成功返回0,失败返回非0
```C
int fsetpos(FILE* stream, const fpos_t* pos);
```
以文件起始位置为基点,偏移pos个字节,确定文件指针在文件中的位置
成功返回0,失败返回非0
```C
//简单示例
#include
int main(void)
{
FILE* fp;
fpos_t position;
fp = fopen("test", "w+");
fgetpos(fp, &position); //#1,将指针fp在文件test中当前位置距离test起始位置的偏移量存入position中
fputs("Hello World!\n", fp); //#2
fsetpos(fp, &position); //#3 利用position的值,来调整指针fp在文件中的位置
fputs("你好,世界!\n",fp); //#4
fclose(fp);
return 0;
}
```
以上示例中 #1利用position记录指针fp距离文件开头的偏移量(字节数),当前指针指向文件起始位置,所以偏移量为0
执行#2后,文件指针fp在文件中的位置发生了改变,
通过#3,以文件起始位置为基点,偏移pos个字节,重新设置fp的位置,所以fp再次指向了文件开头
所以在执行了#4之后,“你好,世界”覆盖了“Hello world”