Linux文件I/O编程(二)

目录

实现cp指令

修改文件某字段内容 

写一个整数到文件

写结构体数组到文件

标准C库文件I/O函数

标准C库函数(fopen、fwrite、fread、fseek、fclose)


实现cp指令

文件名通过参数传入,打开文件 —>读取内容到缓冲区—>缓冲区内容写入目标文件。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc, const char *argv[])
{
        int fdSrc;
        int fdDes;
        int f_size;
        int n_read;
        int n_write;
        char *readbuff = NULL;

        if(argc != 3){
                printf("too few arguments\n");
                return 0;
        }

        printf("instruction:");
        for(int i=0;i<argc;i++){
                printf("%s ",argv[i]);
        }
        putchar('\n');

        //打开被复制文件
        fdSrc = open(argv[1],O_RDONLY);
        if(fdSrc == -1){
                perror("open src file fault:");
                return 0;
        }
        f_size = lseek(fdSrc,0,SEEK_END);//计算文件大小
        lseek(fdSrc,0,SEEK_SET);

        readbuff = (char *)malloc(f_size+1);//初始化缓冲区
        memset(readbuff,'\0',f_size+1);

        n_read = read(fdSrc,readbuff,f_size);//将源文件内容读到缓冲区
        if(n_read == -1){
                perror("read fault");
                exit(-1);
        }
        printf("read %d bytes from %s\n",n_read,argv[1]);
        close(fdSrc);//操作完成,关闭文件

        //打开目标的文件
        fdDes = open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0600);
        if(fdDes == -1){
                perror("open des file fault");
                return 0;
        }
        n_write = write(fdDes,readbuff,strlen(readbuff));//将缓冲区内容写入到目标>文件中
        if(n_write == -1){
                perror("write fault");
                exit(-1);
        }
        printf("write %d bytes to %s\n",n_write,argv[2]);
        close(fdDes);
        return 0;
}

修改文件某字段内容 

打开文件 —> read读取文件内容到程序缓冲区—> 调用“strstr”得到要修改的位置,进行修改—> 缓冲区内容write写回原文件。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc, const char *argv[])
{
        int fd;
        int f_size;
        int n_read;
        int n_write;
        char *readbuff = NULL;

        if(argc != 2){
                printf("too few arguments\n");
                return 0;
        }

        printf("instruction:");
        for(int i=0;i<argc;i++){
                printf("%s ",argv[i]);
        }
        putchar('\n');

        //打开配置文件
        fd = open(argv[1],O_RDWR);
        if(fd == -1){
                perror("open src file fault:");
                return 0;
        }
        f_size = lseek(fd,0,SEEK_END);//计算文件大小
        lseek(fd,0,SEEK_SET);

        readbuff = (char *)malloc(f_size+1);//初始化缓冲区
        memset(readbuff,'\0',f_size+1);

        n_read = read(fd,readbuff,f_size);//将源文件内容读到缓冲区
        if(n_read == -1){
                perror("read fault");
                exit(-1);
        }
        printf("read %d bytes from \"%s\"\n",n_read,argv[1]);
        close(fd);

        /*找到修改的位置*/
        char *tmp = strstr(readbuff,"score=");
        if(tmp==NULL){
                printf("no such string\n");
        }
        tmp = tmp + strlen("score=");
        *tmp = '9';
        *(tmp+1) = '6';

        //重新写入配置文件
        fd = open(argv[1],O_RDWR|O_TRUNC);
        if(fd == -1){
                perror("open file fault");
                exit(-1);
        }
        n_write = write(fd,readbuff,strlen(readbuff));//将缓冲区内容写入到目标文件
中
        if(n_write == -1){
                perror("write fault");
                exit(-1);
        }
        printf("write %d bytes to \"%s\"\n",n_write,argv[1]);
        close(fd);
        return 0;
}

写一个整数到文件

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
        int fd;
        int data = 100;
        int data2 = 0;

        fd = open("./file1",O_RDWR);//打开文件
        write(fd,&data,sizeof(int));//将整数写到文件
        lseek(fd,0,SEEK_SET);//光标回到头部
        read(fd,&data2,sizeof(int));//读取文件内容
        printf("content is: %d\n",data2);
        close(fd);//关闭文件
        return 0;
}

写结构体数组到文件

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>

struct Test
{
        int a;
        char b;
};

int main()
{
        int fd;
        struct Test data1[2] = {{10,'a'},{20,'b'}};
        struct Test data2[2];
        fd = open("./file1",O_RDWR);//打开文件
        write(fd,&data1,sizeof(struct Test)*2);//将数据写到文件
        lseek(fd,0,SEEK_SET);//光标回到头部
        read(fd,&data2,sizeof(struct Test)*2);//读取文件内容
        printf("content is: %d,%c\n",data2[0].a,data2[0].b);
        printf("content is: %d,%c\n",data2[1].a,data2[1].b);
        close(fd);//关闭文件
        return 0;
}

标准C库文件I/O函数

open是UNIX系统调用函数(包括LINUX等),fopen是标准C语言库函数,

因此:

  • open移植性有限。但基于内核的开发驱动开发,用open。也可操作普通正规文件(Regular File)。open与read,write配合使用。

  • fopen移植性好。fopen是用来操作普通正规文件(Regular File)。fopen与fread,fwrite配合使用。 

1.缓冲文件系统

缓冲文件系统的特点是:在内存开辟一个“缓冲区",给程序中的文件使用; 当执行读文件的操作时,从磁盘文件将数据先读入内存“缓冲区",装满后再从内存“缓冲区”依此读出需要的数据。执行写文件的操作时,先将数据写入内存“缓冲区”,待内存“缓冲区”装满后再写入文件。由此可以看出,内存“缓冲区”的大小,影响着实际操作外存的次数,内存“缓冲区"越大,则操作外存的次数就少,执行速度就快、效率高。一般来说,文件“缓冲区”的大小随机器而定。API有:fopen, fclose, fread, fwrite,fgetc,fgets, fputc, fputs, freopen, fseek, ftell, rewind等。

2.非缓冲文件系统

缓冲文件系统是借助文件结构体指针来对文件进行管理,通过文件指针来对文件进行访问,既可以读写字符、字符串、格式化数据,也可以读写二进制数据。非缓冲文件系统依赖于操作系统,通过操作系统的功能对文件进行读写,是系统级的输入输出,它不设文件结构体指针,只能读写二进制文件,但效率高、速度快。API有:open, close, read, write, getc, getchar, putc, putchar等。

总结,就是open无缓冲,fopen有缓冲。 前者与read, write等配合使用,后者与fread,fwrite等配合使用。使用fopen函数,由于在用户态下就有了缓冲,因此进行文件读写操作的时候就减少了用户态和内核态的切换(切换到内核态调用是需要调用系统调用API);而使用open函数,在文件读写时则每次都需要进行内核态和用户态的切换;表现为,如果顺序访问文件,fopen系列的函数要比直接调用open系列的函数快; 如果随机访问文件则相反。

标准C库函数(fopen、fwrite、fread、fseek、fclose)

FILE *fopen(const char *path, const char *mode);

参数:

mode:

r          打开文本文件,用于读。流被定位于文件的开始。                                                   

r+        打开文本文件,用于读写。流被定位于文件的开始。                                                           

w         将文件长度截断为零,或者创建文本文件,用于写。流被定位于文件的开始。                   

w+        打开文件,用于读写。如果文件不存在就创建它,否则将截断它。流被定位于文件的开始。 

a         打开文件,用于追加  (在文件尾写)。如果文件不存在就创建它。流被定位于文件的末尾。     

a+        打开文件,用于追加  (在文件尾写)。如果文件不存在就创建它。读文件的初始位置是文件的开始,但是输出总是被追加到文件的末尾。

用fopen写字符串到文件

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main()
{
        FILE *fs = NULL;
        char writebuff[] = "12345";
        char *readbuff = NULL;

        //打开文件
        fs = fopen("./file1","r+");//可读可写方式打开文件
        if(fs == NULL){
                perror("open file fail");
        }

        //写入文件
        int n_write = fwrite(writebuff,1,strlen(writebuff),fs);
        printf("write %d bytes\n",n_write);

        //计算文件大小
        int f_size = ftell(fs);//返回当前位置值
        readbuff = (char *)malloc(f_size+1);
        memset(readbuff,'\0',f_size+1);

        //读取文件
        fseek(fs,0,SEEK_SET);
        int n_read = fread(readbuff,1,f_size,fs);
        if(ferror(fs)){
                printf("read file fail\n");
        }
        printf("read %d bytes,%s\n",n_read,readbuff);

        fclose(fs);
        return 0;
}

用fopen写结构体数组到文件

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef struct Test
{
        int a;
        char b;
}TEST;

int main()
{
        FILE *fs = NULL;
        TEST arr[] = {{11,'a'},{22,'c'}};
        TEST *arr2;
        //打开文件
        fs = fopen("./file1","r+");
        if(fs == NULL){
                perror("open file fail");
        }

        //写入文件
        int n_write = fwrite(arr,sizeof(arr),1,fs);
        printf("write %d memb\n",n_write);

        //计算文件大小
        int f_size = ftell(fs);//返回当前位置值
        arr2 = (TEST *)malloc(f_size);

        //读取文件
        fseek(fs,0,SEEK_SET);
        int n_read = fread(arr2,f_size,1,fs);
        if(ferror(fs)){
                printf("read file fail\n");
        }
        printf("read %d members,%d,%c,%d,%c\n",n_read,arr2[0].a,arr2[0].b,arr2[1].a,arr2[1].b);

        fclose(fs);
        return 0;
}

其他C库函数:

除了用fwrite、fread,还可以用fputc和fgetc逐个字符写入和读取。

fgetc():

C 库函数 int fgetc(FILE *stream) 从指定的流 stream 获取下一个字符(一个无符号字符),并把位置标识符往前移动。

返回值:该函数以无符号 char 强制转换为 int 的形式返回读取的字符,如果到达文件末尾或发生读错误,则返回 EOF。

fputc():

C 库函数 int fputc(int char, FILE *stream) 把参数 char 指定的字符(一个无符号字符)写入到指定的流 stream 中,并把位置标识符往前移动。

feof():

C 库函数 int feof(FILE *stream) 测试给定流 stream 的文件结束标识符。返回值:到文件尾巴时返回非0,其它返回0。

ferror():

C 库函数 int ferror(FILE *stream),在调用各种输入输出函数(如 putc.getc.fread.fwrite等)时,如果出现错误,调用ferror会返回非0值,返回0表示未出错。

demo:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main()
{
        FILE *fs = NULL;
        char *writebuff = "12345";
        char *readbuff = NULL;

        //打开文件
        fs = fopen("./file1","r+");
        if(fs == NULL){
                perror("open file fail");
        }

        //写入文件
        while(*writebuff){
                fputc(*writebuff,fs);
                writebuff++;
        }
        if(ferror(fs)){
                printf("write file fail\n");
        }

        //计算文件大小
        int f_size = ftell(fs);//返回当前位置值
        readbuff = (char *)malloc(f_size+1);
        memset(readbuff,'\0',f_size+1);

        //读取文件
        fseek(fs,0,SEEK_SET);
        int i = 0;
        char a;
        a = fgetc(fs);
        while(feof(fs) == 0){//检查文件结束符,如果文件结束返回非0,否则返回0
                readbuff[i] = a;
                a = fgetc(fs);
                i++;
        }
        if(ferror(fs)){
                printf("read file fail\n");
        }
        printf("read,%s\n",readbuff);

        fclose(fs);
        return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值