C语言分析——文件操作

来源:互联网 发布:软件模块接口参数 编辑:程序博客网 时间:2024/06/05 14:33

  • 文件操作工具函数
    • 相对路径转换函数realpath
    • 设置文件当前指针fseek
  • 读取文件
    • 读取一个字符函数fgetc
    • 读取一个字符串函数fgets
    • 格式化读取字符串函数fscanf
  • 写入文件
    • 写入一个字符函数fputc
    • 写入一个字符串函数fputs
    • 格式化写入字符串函数fprintf
    • 写入一个块文件函数fwrite

头文件:#include

文件操作工具函数

相对路径转换函数:realpath

头文件:#include

设置文件当前指针:fseek

原型:int fseek(FILE *stream, long offset, int fromwhere)
功能:设置文件指针的位置。

参数:
offset:偏移量,以字节为单位正数表示正向偏移,负数表示负向偏移。
fromwhere:偏移起始位置

#define     SEEK_SET        0   //文件头#define     SEEK_CUR        1   //当前位置#define     SEEK_END        2   //文件尾

例如

fseek(fp,56L,0);        //把fp指针移动到从文件开头起始,往正方向的56个字节处;fseek(fp,34L,1);        //把fp指针移动到从当前位置起始,往正方向的34个字节处;fseek(fp,-78L,2);       //把fp指针移动到从结尾位置起始,往负方向的78个字节处。

读取文件

读取的文本文件:read.txt

test read txt adminThis is a read test.

文本文件的第三行有一个回车

读取一个字符函数:fgetc

函数原型:int fgetc(FILE *stream);

功能:从文件流steam中读取一个字符。

源码

static int Test_fgetc(int argc,char *argv[]){    char ch = 0;                    //字符保存缓冲区    if(NULL == argv[1])    {        return -1;    }    char *real_path = realpath(argv[1],0);  //相对路径转换绝对路径    FILE *fp = fopen(real_path,"r");        //打开文件    if(!fp)    {        printf("%s can not be opened.\n",argv[1]);        return -1;    }    while((ch = fgetc(fp))!=EOF)    //判断读取的字符是否是文件结束符      {          putchar(ch);                //输出字符     }     fclose(fp);     return 0;}

运行结果

$ ./prj/project.o read.txt test read txt adminThis is a read test.$

读取一个字符串函数:fgets

函数原型:char *fgets(char *s, int size, FILE *stream);

该函数读到一个回车键就结束了,读取字符串的时候一定要注意读取的文件包含的回车键。

源码:

static int Test_fgets(int argc,char *argv[]){    if(NULL == argv[1])    {        return -1;    }    char *real_path = realpath(argv[1],0);    FILE *fp = fopen(real_path,"r");    if(!fp)    {        printf("%s can not be opened.\n",argv[1]);        return -1;    }    fseek(fp,0L,SEEK_END);          //定位到文件末尾    int flen = (int)ftell(fp);          //获取得到文件大小    fseek(fp,0L,SEEK_SET);    char *chs = (char *)malloc(flen+1);     //分配空间    if(chs == NULL)    {        fclose(fp);        return 0;    }memset((void *)chs,0,flen+1);       fgets(chs,flen,fp); //由于读取的文件有两行因此读取两次结果    printf("%s",chs);    fgets(chs,flen,fp);     printf("%s",chs);free(chs);    fclose(fp); chs = NULL;    return 0;}

执行结果

$ ./prj/project.o read.txt test read txt adminThis is a read test.$

格式化读取字符串函数:fscanf

函数原型:int fscanf(FILE *stream, const char *format, …);

该函数读到一个空格键就结束了,读取字符串的时候一定要注意读取的文件包含的空格键。该函数一般作为读取类似表格数值时使用。

1、作为读取函数
源码

static int Test_fscanf(int argc,char *argv[]){    if(NULL == argv[1])    {        return -1;    }    char *real_path = realpath(argv[1],0);    FILE *fp = fopen(real_path,"r");    if(!fp)    {        printf("%s can not be opened.\n",argv[1]);        return -1;    }    fseek(fp,0L,SEEK_END);          //定位到文件末尾    int flen = (int)ftell(fp);          //获取得到文件大小    fseek(fp,0L,SEEK_SET);    char *pchs = (char *)malloc(flen+1);    //分配空间    if(pchs == NULL)    {        fclose(fp);        return 0;    }    memset((void *)pchs,0,flen+1);    (void)fscanf(fp,"%s",pchs);         //由于读取的文件有两行因此读取两次结果    printf("%s\n",chs);    (void)fscanf(fp,"%s",pchs);    printf("%s\n",chs);    free(pchs);    fclose(fp);     chs = NULL;    return 0;}

执行结果

$ ./prj/project.o read.txt testread$

可以看到,读取的字符串只读到了空格键就结束了。

通过 改变读取规则,来读取到回车键结束的字符串。
源码

    (void)fscanf(fp, "%[^\n]%*c",pchs );    printf("%s\n",pchs );    (void)fscanf(fp, "%[^\n]%*c",pchs );    printf("%s\n",pchs );

读取规则:”%[^\n]%*c”
%[ ]表示读取指定字符集的文本,[^’\n’]表示读取非’\n’字符的所有字符,%*[^\n]%*c表示跳过一行。

执行结果

$ ./prj/project.o read.txt test read txt adminThis is a read test.$

2、作为读取类似表格的数值时

读取文件:table.txt

admin   1       rootguest    2      user

源码

static int Test_fscanf_table(int argc,char *argv[]){    if(NULL == argv[1])    {        return -1;    }    char *real_path = realpath(argv[1],0);    FILE *fp = fopen(real_path,"r");    if(!fp)    {        printf("%s can not be opened.\n",argv[1]);        return -1;    }    User_info Test_User_info;   //读取文本中的数值    while((fscanf(fp, "%s %d %s",Test_User_info.name,&Test_User_info.permissions,Test_User_info.group)) != EOF)    {           printf("name        is %s\n",Test_User_info.name);        printf("permissions is %d\n",Test_User_info.permissions);        printf("group       is %s\n",Test_User_info.group);     }       fclose(fp);     return 0;}

执行结果

$ ./prj/project.o table.txt name            is adminpermissions is  1group           is rootname            is guestpermissions is  2group           is user$

1.3.2.4 读取一个块文件函数:fread
函数原型:size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

传入参数:*ptr:size:nmemb:*steam:返回值:读到的字节数

1、读取字符串信息的文件。
源码:

static int Test_fread(int argc,char *argv[]){    if(NULL == argv[1])    {        return -1;    }    char *real_path = realpath(argv[1],0);    FILE *fp = fopen(real_path,"r");    if(!fp)    {        printf("%s can not be opened.\n",argv[1]);        return -1;    }    fseek(fp,0L,SEEK_END);          //定位到文件末尾    int flen = (int)ftell(fp);          //获取得到文件大小    fseek(fp,0L,SEEK_SET);    char *pchs  = (char *)malloc(flen+1);   //分配空间    if(pchs  == NULL)    {        fclose(fp);        return 0;    }       memset((void *)pchs ,0,flen+1);    fread(pchs,flen,sizeof(char),fp);       //读取整个文件信息    printf("%s",pchs );             //打印信息    free(pchs );    fclose(fp);     pchs  = NULL;    return 0;}

执行结果

$ ./prj/project.o read.txt test read txt adminThis is a read test.$

2、读取表格信息的文件
由于fread为连续读取,不分空格的情况,也不分存储类型,按文档的形式(以bin文件存储或以字符形式存储),因此是要连续的表格形式文件。

连续的表格形式的bin文件readtable.bin

$ hexdump readtable.bin 0000000 6461 696d 006e 0000 0000 6f72 746f 00000000010 0000 0000 0001 0000 7567 7365 0074 00000000020 0000 7375 7265 0000 0000 0000 0002 00000000030$

hex格式查询即为
这里写图片描述

源码

static int Test_fread_table(int argc,char *argv[]){    if(NULL == argv[1])    {        return -1;    }    char *real_path = realpath(argv[1],0);    FILE *fp = fopen(real_path,"r");    if(!fp)    {        printf("%s can not be opened.\n",argv[1]);        return -1;    }    User_info Test_User_info= {0};  //数据读取缓冲区//读取结构体    while((fread(&Test_User_info,1,sizeof(User_info),fp)) == sizeof(User_info))    {        printf("name        is %s\n",Test_User_info.name);        printf("permissions is %d\n",Test_User_info.permissions);        printf("group       is %s\n",Test_User_info.group);     }    fclose(fp);     return 0;}

执行结果

$ ./prj/project.o readtable.bin name        is adminpermissions is 1group       is rootname        is guestpermissions is 2group       is user$

写入文件

写入一个字符函数:fputc

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

功能:将一个字符写入文件流steam中。
源码:

static int Test_fputc(int argc,char *argv[]){    const char *pch = "This is test fputc"; //字符保存缓冲区    if(NULL == argv[1])    {        return -1;    }    char *real_path = realpath(argv[1],0);    FILE *fp = fopen(real_path,"w");    if(!fp)    {        printf("%s can not be opened.\n",argv[1]);        return -1;    }    int len = strlen(pch);    while(len--)    {          fputc(*pch++,fp);   //写入字符     }     fputc('\n',fp);         //写入回车键    fclose(fp);     return 0;}

执行结果

$ ./prj/project.o write.txt $ cat write.txt This is test fputc$

写入一个字符串函数:fputs

函数原型:int fputs(const char *s, FILE *stream);

功能:将一个字符串写入文件流steam中。
源码:

static int Test_fputs(int argc,char *argv[]){    const char *pchs = "This is test fputs";    //字符保存缓冲区    if(NULL == argv[1])    {        return -1;    }    char *real_path = realpath(argv[1],0);    FILE *fp = fopen(real_path,"w");    if(!fp)    {        printf("%s can not be opened.\n",argv[1]);        return -1;    }    fputs(pchs,fp);         //写入字符      fputc('\n',fp);     //写入回车键    fclose(fp);     return 0;}

执行结果

$ ./prj/project.o write.txt$ cat write.txt This is test fputs$

格式化写入字符串函数:fprintf

函数原型:int fprintf(FILE *stream, const char *format, …);

和printf打印函数类似,只是printf将结果输出到屏幕上,而fpritntf则是将结果输出到文件中。

源码

static int Test_fprintf(int argc,char *argv[]){    if(NULL == argv[1])    {        return -1;    } char real_path[80];    realpath(argv[1],real_path);    FILE *fp = fopen(real_path,"w");    if(!fp)    {        printf("%s can not be opened.\n",argv[1]);        return -1;    }    User_info Test_User_info[2] = {     //定义写入结构体        {"admin",1,"root"},        {"guest",2,"user"},    };    (void)fprintf(fp,"fprintf test name is %s permissions is %d and group is %s\n",                  Test_User_info[0].name,Test_User_info[0].permissions,Test_User_info[0].group);    (void)fprintf(fp,"fprintf test name is %s permissions is %d and group is %s\n",                  Test_User_info[1].name,Test_User_info[1].permissions,Test_User_info[1].group);    fclose(fp);    return 0;}

执行结果

$ ./prj/project.o write.txt $ cat write.txt fprintf test name is admin permissions is 1 and group is rootfprintf test name is guest permissions is 2 and group is user$

写入一个块文件函数:fwrite

函数原型:size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);

写入整个文件块函数,可以写入字符串,也可以写入结构体数值。

1、写入字符串源码

static int Test_fwirte(int argc,char *argv[]){    if(NULL == argv[1])    {        return -1;    }    char *real_path = realpath(argv[1],0);    FILE *fp = fopen(real_path,"w");    if(!fp)    {        printf("%s can not be opened.\n",argv[1]);        return -1;    }    const char *pchs[2] = {        "This is test fwrite 1.",        "This is test fwrite 2.",       };    fwrite(pchs[0],strlen(pchs[0]),1,fp);    fwrite(pchs[1],strlen(pchs[1]),1,fp);    fputc('\n',fp);    fclose(fp);     return 0;}

执行结果

$ ./prj/project.o write.txt $ cat write.txt This is test fwrite 1.This is test fwrite 2.$

2、写入结构体数值函数源码

static int Test_wirte_table(int argc,char *argv[]){    if(NULL == argv[1])    {        return -1;    }    char *real_path = realpath(argv[1],0);    FILE *fp = fopen(real_path,"wb");    if(!fp)    {        printf("%s can not be opened.\n",argv[1]);        return -1;    }    User_info Test_User_info[2] = {        {"admin",1,"root"},        {"guest",2,"user"}    };          (void)fwrite(&Test_User_info,sizeof(User_info),2,fp);   //写入结构体    fclose(fp);     return 0;}

执行结果

$ ./prj/project.o writetable.bin $ hexdump writetable.bin 0000000 6461 696d 006e 0000 0000 6f72 746f 00000000010 0000 0000 0001 0000 7567 7365 0074 00000000020 0000 7375 7265 0000 0000 0000 0002 00000000030$

hex格式查询即为
这里写图片描述