C语言文件操作详解

C语言有关文件操作的函数主要有下面这些:

  1. fopen:打开一个文件
  2. fclose:关闭一个文件
  3. fgetc:从文件中读取一个字符
  4. fputc:向文件中写入一个字符
  5. fgets:从文件中读取一个字符串
  6. fputs:向文件中写入一个字符串
  7. fprintf:向文件中格式化写入数据
  8. fscanf:从文件中格式化读取数据
  9. fread:以二进制形式从文件中读取数据
  10. fwrite:以二进制形式向文件中写入数据
  11. getw:以二进制形式从文件中读取一个整数
  12. putw:以二进制形式向文件中写入一个整数
  13. feof:文件结束
  14. ferror:文件读写错误
  15. clearerr:清除文件错误日志
  16. ftell:了解文件指针当前位置
  17. rewind:反绕
  18. fseek:随机定位

下面详细讲解一下各个函数的用法:

1、fopen、fclose


fopen

函数原型:FILE * fopen(const char * path, const char * mode)

参数path字符串包含将要打开的文件路径及文件名,参数mode字符串则代表着流形态。

文件顺利打开后,指向该流的文件指针就会被返回。如果文件打开失败则返回NULL,并把错误代码放在error中。

mode有下列几种形态字符串:


上述的形态字符串都可以再加一个 b 字符,如 rb、w+b 或 ab+ 等组合,加入 b 字符用来告诉函数库以二进制模式打开文件。如果不加 b,表示默认加了 t,即 rt、wt,其中 t 表示以文本模式打开文件。


fclose

函数原型:int fclose( FILE *fp )

如果流成功关闭,fclose 返回 0,否则返回EOF(-1)

可以在fclose(fp)后使用

if(fclose())
{
    perror("fclose");
}

来判断是否成功关闭文件,关闭失败,则fclose返回1并输出错误原因

函数应用实例:

#include<stdio.h>
int main()
{
    FILE *fp = NULL;
    fp = fopen("text.txt","r");
    if(fp == NULL)
        return -1;
    fclose();
    fp = NULL;//需要指向空,否则会指向原打开文件地址
    return 0;
}
2、fgetc、fputc


fgetc

函数原型:int fgetc(FILE *fp)

文件指针fp指向的文件中读取一个字符,读取一个字节后,光标位置后移一个字节。这个函数的返回值,是返回所读取的一个字节。如果读到文件末尾或者读取出错时返回EOF。

注意到虽然是返回一个字节,但是返回值类型为int而不知unsigned char,因为EOF为-1,返回值要能够表示-1。



fputc

函数原型:int fputc (int c, FILE *fp)

c是一个整型变量,是内存要写到文件中的字符(C语言中整型量和字符量可以通用)

在正常调用情况下,函数返回写入文件的字符的ASC||码值,出错时,返回EOF。当正确写入一个字符或一个字节的数据后,文件内部写指针会自动后移一个字节的位置。

函数应用实例:将一个文件中的大写字母转为小写字母,小写字母转为大写字母后保存到另一个文件中

#include<stdio.h>
int main()
{
    char ch;
    FILE *fp1,*fp2;
    fp1 = fopen("a.txt","r");
    if(fp1 == NULL)
        return -1;
    fp2 = fopen("b.txt","w");
    if(fp2 == NULL)
        return -1;
    ch = fgetc(fp1);
    while(ch != EOF)
    {
        if(ch >= 'a' && ch <= 'z')
            ch -= 32;
        else if(ch >= 'A' && ch <= 'Z')
            ch += 32;
        fputc(ch,fp2);
        ch = fgetc(fp1);
    }
    fclose(fp1);
    fp1 = NULL;
    fclose(fp2);
    fp2 = NULL;
    return 0;
}
3、fgets、fputs


fgets

函数原型:char *fgets(char *str,int n,FILE *fp)

从由fp指出的文件中读取n-1个字符(因为第n个是'\0'),并把它们存放到由str指出的字符串数组中去,最后加上一个字符串结束符'\0'。如果文件中的该行不足n个字符,则读完该行就结束。若该行(包括最后一个换行符)的字符数超过n-1,则只返回一个不完整的行,但是,缓冲区总是以NULL字符结尾,对fgets的下一次调用会继续该行。函数成功将返回指向str的指针,失败或读到文件结尾返回NULL,因此不能直接通过fgets的返回值来判断函数是否是出错而终止的,应该借助feof函数或ferror函数来判断。

str:接收字符串的内存地址,可以是数组名,也可以是指针。

n:指出要读取字符串的个数。

fp:这是个文件指针,指出要读取的文件。



fputs

函数原型:int fputs(char *str,FILE *fp)

str是字符型指针,可以是字符串常量,或者存放字符串的数组首地址。

fp是文件指针。

向fp指向的文件写入一个字符串(不自动写入字符串结束标记符'\0')。成功写入一个字符串后,文件的位置指针会自动后移,函数返回值为非负整数,否则返回EOF。

函数应用实例:测试fgets

#include<stdio.h>
int main(int argc,char **argv)
{
    FILE *fp1;
    char str[256];
    fp1 = fopen("a.txt","r");//a.txt中的内容是ABCabc123
    if(fp1 == NULL)
        return -1;

    if(fgets(str,4,fp1) == NULL)//这里调用fgets一次,读取出3个字符
        printf("失败");
    else
        printf("%s\n",str);

    if(fgets(str,7,fp1) == NULL)//这里第二次调用fgets,读取出剩下的6个字符
    {
        printf("失败");
    }
    else
        printf("%s\n",str);

    if(fgets(str,2,fp1) == NULL)//由于文件已经读取完毕,因此返回NULL
        printf("失败");
    else
        printf("%s",str);
    return 0;
}

函数应用实例:将一个文件中的内容复制到另一个文件

#include<stdio.h>
int main(int argc,char **argv)
{
    FILE *fp1,*fp2;
    char str[256];
    fp1 = fopen("a.txt","r");//a.txt中的内容是ABCabc123
    fp2 = fopen("b.txt","w");//b.txt为空
    if(fp1 == NULL)
        return -1;
    if(fp2 == NULL)
        return -1;

    if(fgets(str,4,fp1) == NULL)//这里调用fgets一次,读取出3个字符
        printf("失败");
    else
        fputs(str,fp2);

    if(fgets(str,7,fp1) == NULL)//这里第二次调用fgets,读取出剩下的6个字符
        printf("失败");
    else
        fputs(str,fp2);

    if(fgets(str,2,fp1) == NULL)//由于文件已经读取完毕,因此返回NULL
        printf("失败");
    else
        fputs(str,fp2);
    return 0;
}
4、fscanf、fprintf


fscanf

函数原型:int fscanf(FILE *fp,const char * format,[argument...])

fp:文件指针

format:格式化数据

根据数据格式(format)从输入流fp中写入数据,与fgets的差别在于:fscanf遇到空格和换行符时结束,注意空格时也结束,fgets遇到空格不结束。

(其实就是平时使用的scanf,只是需要指明操作的文件流罢了) 




fprintf

函数原型:int fprintf(FILE *fp,const char *format,[argument]....)

根据指定的format发送信息由fp指定的文件,fprintf()只能和printf()一样工作,fprintf()的返回值是输出指定的字符串,发生错误时返回一个负值。


函数应用实例:格式化读取a.txt中的数据写入b.txt中

#include<stdio.h>
int main(int argc,char **argv)
{
    FILE *fp1,*fp2;
    int a,b,c,d;
    fp1 = fopen("a.txt","r");
    fp2 = fopen("b.txt","w");
    if(fp1 == NULL)
        return -1;
    if(fp2 == NULL)
        return -1;
    while(!feof(fp1))
    {
        fscanf(fp1,"%d %d %d %d",&a,&b,&c,&d);
        fprintf(fp2,"%d %d %d %d\n",a,b,c,d);
    }
    return 0;
}


5、fread、fwrite



fread

函数原型:size_t fread (void * buffer,size_t size,size_t count,FILE *fp)

size_t是标准C库中定义的,应为unsigned int,在64位系统中为long unsigned int

buffer:用于接收数据的内存地址

size:要读的每个数据项的字节数,单位是字节

count:要读count个数据项,每个数据项size个字节

fp:要进行操作的文件流

如果读取成功,则返回真实读取的项数,若大于count则意味着产生了错误。



fwrite

函数原型:

size_t fwrite(const void* buffer,size_t size,size_t,count,FILE *fp)

buffer:是一个指针,对fwrite来说,是要获取数据的地址

size:要写入内容的单字字节数

count:要进行写入size字节的数据项个数

fp:文件指针

如果写入成功则返回实际写入的数据块数目。


函数应用实例:将a中的9个字母复制到b中,每次复制3个字母

#include<stdio.h>
int main(int argc,char **argv)
{
    FILE *fp1,*fp2;
    int a[3];
    fp1 = fopen("a.txt","rb");
    fp2 = fopen("b.txt","wb");
    if(fp1 == NULL)
    {
        printf("打开a失败");
        return -1;
    }
    if(fp2 == NULL)
    {
        printf("打开b失败");
        return -1;
    }

    if(fread(a,sizeof(char),3,fp1)!=0)
        fwrite(a,sizeof(char),3,fp2);
    if(fread(a,sizeof(char),3,fp1)!=0)
        fwrite(a,sizeof(char),3,fp2);
    if(fread(a,sizeof(char),3,fp1)!=0)
        fwrite(a,sizeof(char),3,fp2);
    if(fread(a,sizeof(char),3,fp1)!=0)
        fwrite(a,sizeof(char),3,fp2);
    return 0;
}



6、getw、putw



getw

函数原型:int getw(FILE *fp)

从fp所指向的文件读取下一个字(整数),返回读入的整数,如果文件结束或出错返回-1。



putw

函数原型:int putw(int w,FILE *fp)

将整数w写入fp指向的文件,返回输出的整数,如果出错,则返回EOF


这两个函数好像是以ASCII码值来读取和写入数据的,getw每次会读取4个ASCII码值的数据,如果一次读取的数据不足4个就会返回EOF(注意此时无法用putw写入剩下的数据),而且如果写入时w中不足4个数据,打开文件会发现后面不足的数据会追加上空格。这???是什么???博主也没有彻底搞懂这两个函数是怎么工作的尴尬,哪位大佬如果知道的话可以提醒一下我....


函数应用实例:将a中的数字复制到b中

#include<stdio.h>
int main(int argc,char **argv)
{
    FILE *fp1,*fp2;
    int n;
    fp1 = fopen("a.txt","rb");
    fp2 = fopen("b.txt","wb");
    if(fp1 == NULL)
        return -1;
    if(fp2 == NULL)
        return -1;

    n = getw(fp1);
    while(n != -1)
    {
        putw(n,fp2);
        n = getw(fp1);
    }
    return 0;
}



7、feof

函数原型:int feof(FILE *fp)

如果文件结束,则返回非0值,否则返回0.

函数应用实例:

#include<stdio.h>
int main(int argc,char **argv)
{
    FILE *fp;
    int ch;
    fp = fopen("a.txt","r");//a中的数据是123456
    if(fp == NULL)
        return -1;
    for(int i=0;i<7;i++)
    {
        ch = fgetc(fp);
        printf("%d\n",feof(fp));
    }
    return 0;
}


8、ferror

函数原型:int ferror(FILE *fp)

在调用各种输入输出函数(如putc,getc,fread,fwrite等)时,如果出现错误,除函数返回值有所反映外,还可以用ferror函数检查。 它的一般调用形式为 ferror(fp);如果ferror返回值为0(假),表示未出错。如果返回一个非零值,表示出错。(读到文件末尾不算出错)


函数应用实例:

#include<stdio.h>
int main(int argc,char **argv)
{
    FILE *fp;
    int ch;
    fp = fopen("a.txt","r");//a中的数据是123456
    if(fp == NULL)
        return -1;
    for(int i=0;i<7;i++)
    {
        ch = fgetc(fp);
        printf("%d\n",ferror(fp));
    }
    return 0;
}
//输出结果:0000000


9、clearerr

函数原型:void clearerr(FILE *fp)

clearerr的作用是使文件错误标志和文件结束标志置为0,假设在调用一个输入输出函数时出现了错误,ferror函数值为一个非0值。在调用clearerr(fp)后,ferror(fp)的值变为0。


10、ftell

函数原型:long ftell(FILE *fp)

函数ftell用于得到文件位置指针当前位置相对于文件首的偏移字节数。在随机方式存取文件时,由于文件位置频繁的前后移动,程序不容易确定文件的当前位置。

因为ftell返回long类型,根据long型的取值范围-2^31~2^31-1,故对大于2.1G的文件进行操作时出错。


函数应用实例:

#include<stdio.h>
int main(int argc,char **argv)
{
    FILE *fp;
    int ch;
    fp = fopen("a.txt","r");//a中的数据是123456
    if(fp == NULL)
        return -1;
    for(int i=0;i<7;i++)
    {
        ch = fgetc(fp);
        printf("%d\n",ftell(fp));
    }
    return 0;
}
//输出结果:1234566



11、fseek

函数原型:int fseek(FILE *fp,long offset,int fromwhere)

如果执行成功,fp将指向以fromwhere为基准,偏移offset(指针偏移量,可以为负)个字节的位置,函数返回0,如果执行失败(比如offset超过文件自身大小),则不改变fp指向的位置,函数返回非0值。

fromwhere的可能取值为SEEK_CUR,SEEK_END,SEEK_SET

SEEK_SET:文件开头

SEEK_CUR:当前位置

SEEK_END:文件结尾

其中SEEK_SET,SEEK_CUR,SEEK_END依次为0,1,2

应用中一般会用count*sizeof(数据类型)来表示offset,使用该函数后可以使用ftell来得到文件指针位置。(注意文本文件中一个数字1字节,一个小写字母1字节,一个大写字母1字节,一个制表符1字节,可以自己建立文本文件写入一个字符试一下,我在我电脑上测试的是这样)



函数应用实例:

#include<stdio.h>
int main(int argc,char **argv)
{
    FILE *fp;
    int ch;
    fp = fopen("a.txt","r");//a中的数据是ABC123456
    if(fp == NULL)
        return -1;

    printf("%d\n",ftell(fp));//输出刚开始的指针位置

    ch = getc(fp);
    printf("%c\n",ch);
    printf("%d\n",ftell(fp));//读取一个字符,此时指针应该后移1位,输出此时的位置

    fseek(fp,3,SEEK_CUR);//向后移动3个字节
    printf("%d\n",ftell(fp));//输出此时的位置

    ch = getc(fp);//继续读取后面的字符
    printf("%c\n",ch);
    return 0;
}
//输出结果:0A142



12、rewind

函数原型:void rewind(FILE *fp)

将文件内部的位置指针重新指向流的开头。

注意:不是文件指针而是文件内部的位置指针,随着对文件的读写,文件的位置指针向后移动。而文件指针是指向整个文件,如果不重新赋值文件指针不会改变。

rewind函数的作用等同于(void)fseek(fp,0,SEEK_SET)。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值