C语言文件读写fread, fwrite, fseek

本文已整合到C语言标准库深度解读

打开文件

fopenfreopen均为C语言标准库stdio.h中的函数,分别用于打开和重新打开某个stream,二者均返回一个FILE指针。

  • FILE *fopen(const char *filename, const char *mode)
  • FILE *freopen(const char *filename, const char *mode, FILE *stream)

其中filename为文件路径,mode为文件打开模式,freopen中输入的的stream为现存的流,freopen将新打开的文件注入stream中,同时关闭旧文件。

其中mode的取值如下,第一列为常规模式,第二列为二进制模式,在二进制模式下,读取的是二进制文件,其他与常规模式相同。

mode模式说明
“r”“rb”只读打开的文件必须存在。
“w”“wb”写入创建一个空文件,若文件已存在,会删除原有内容。
“a”“ab”追加向文件末尾追加数据,若文件不存在,则创建文件。
“r+”“rb+”更新打开一个文件进行读写,该文件必须存在。
“w+”“wb+”读写创建一个用于读写的空文件。
“a+”“ab+”打开一个用于读取和追加的文件

fopenfreopen的返回值为FILE指针,刚好可以通过stdio.h中的close进行关闭。

关于FILE这个结构体,可见FILE结构体

文件读写

stdio.h中定义了读、写还有移动指针的函数,其中fread用于将文件中的数据写入内存;fwrite将内存中的数据写入文件;fseek则操作文件指针,使之偏移,从而可以更加灵活地读取。

  • 读:size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
  • 写:size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
  • 移:int fseek(FILE *stream, long int offset, int whence)

其中,ptr为指向某个内存块的指针;stream为文件的数据流;nmemb为元素个数,size为每个元素的字节数;whence为添加偏移的位置,offset为相对于whence的偏移量。

stdio.h中为whence定义了宏,其含义如下

#define SEEK_SET 0从0开始
#define SEEK_CUR 1从当前位置开始
#define SEEK_END 2从EOF开始

读写相对来说比较直观,接下来主要测试一下fseek,说明均在注释中。

//test.c
#include<stdio.h>
void printChar(char *buffer, int len){
	for(int i = 1; i < len; i++)
		printf("%c",buffer[i-1]);
	printf("\n-------------------------\n");
}
int main(){
    FILE* fp = fopen("test.c","r"); //打开test.c文件,即本文件

    char buf[20];
    fread(buf,1,20,fp);          //读取fp中的数据
    printf("printf the first 20 bytes:");
    printChar(buf,20);

    fseek(fp, 24, SEEK_CUR);    //从当前位置开始偏移
    fread(buf,1,20,fp);
    printf("fseek 24 from now:");
    printChar(buf,20);

    fseek(fp, 24, SEEK_SET);    //从0开始偏移
    fread(buf,1,20,fp);
    printf("fseek 24 from 0:");
    printChar(buf,20);

    fseek(fp, -20, SEEK_END);    //从结束位置向前偏移
    fread(buf,1,20,fp);
    printf("fseek 20 from END:"); 
    printChar(buf,20);

    fclose(fp);         //关闭fp
    return 0;
}

输出结果为

>gcc test.c

E:\Documents\00\1217>a.exe
printf the first 20 bytes://test.c
#include<s
-------------------------
fseek 24 from now:har *buffer, int le
-------------------------
fseek 24 from 0:.h>
void printChar(
-------------------------
fseek 20 from END:
    return 0;
}
r(
-------------------------

文件定位

除了fseek可以对文件指针进行移动之外,fsetpos可以直接对文件指针进行定位。相应地,fgetpos可以获取文件指针的位置,二者声明为:

  • int fgetpos(FILE *stream, fpos_t *pos)
  • int fsetpos(FILE *stream, const fpos_t *pos)

二者的返回值均为设置之后的位置,关于输入参数,FILE *stream是大家非常熟悉的文件流,而fpos_t是一个结构体,代表相对位置,通常定义为

typedef struct
{
    unsigned long _off;
}fpos_t;

接下来做一个简单的测试

//pos.c
#include <string.h>
#include <stdio.h>
int main(void)
{
    fpos_t pos;
    FILE* fp = fopen("pos.c", "r"); //打开pos.c文件,即本文件
    fgetpos(fp, &pos);              //获取指针位置
    printf("file pointer : %ld\n", pos);
    
    fseek(fp,10,0);         // 移动指针位置
    fgetpos(fp, &pos);      // 获取指针位置并存入&pos所指向的对象
    printf("file pointer : %ld\n", pos);
    fclose(fp);
    return 0;
}

结果如下,可见getposfseek的单位是一致的,fseek移动了10个字节,则fgetpos也获取了位置10.

>gcc pos.c
>a.exe
file pointer : 0
file pointer : 10

结合fgetposfsetpos,可完成类似fseek的操作

//setpos.c
#include <string.h>
#include <stdio.h>
int main(void)
{
    fpos_t pos;
    FILE* fp = fopen("pos.c", "r");   //打开pos.c文件,即本文件
    printf("file pointer : %ld\n", fgetpos(fp, &pos));
    
    pos += 10;
    fsetpos(fp, &pos);      //设置指针位置
    printf("file pointer : %ld\n", fgetpos(fp, &pos));
    fclose(fp);
    return 0;
}

测试结果为

>gcc setpos.c
>a.exe
file pointer : 0
file pointer : 10
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

微小冷

请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值