我是靠谱客的博主 喜悦往事,最近开发中收集的这篇文章主要介绍Linux系统编程 文件,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

一、打开及创建

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

int main()
{
        int fd;
        fd = open("./file1",O_RDWR);
        if(fd == -1)
        {
                printf("open file1 failedn");
                fd = open("./file1",O_RDWR|O_CREAT,0600);
                if(fd > 0)
                {
                        printf("creat file1 successn");
                }
        }
        return 0;
}

在这里插入图片描述
函数返回一个描述符

O_RDONLY:可读
O_WRONLY:可写
O_RDWR:可读可写

ls -l:列出所有文件清单
在这里插入图片描述
-rwxr-xr-x 权限
可读:r 4
可写:w 2
执行:x 1
0600 代表 4+2 权限 :可读可写
给文件所有者CLC权限

二、文件的写入
cat file1 查看文本file1的内容

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main()
{
        int fd;
        char *buf = "wo shi nen die!";
        fd = open("./file1",O_RDWR);
        if(fd == -1)
        {
                printf("open file1 failedn");
                fd = open("./file1",O_RDWR|O_CREAT,0600);
                if(fd > 0)
                {
                        printf("creat file1 successn");
                }
        }
        printf("open success!n:fd = %dn",fd);
        write(fd,buf,strlen(buf));
        close(fd);
        return 0;
}

在这里插入图片描述
在这里插入图片描述
文件打开写入后要close
Linux下指针分配8个字节
计算长度不能用sizeof ()要用 strlen()

三、文件的读取

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main()
{
        int fd;
        char *buf = "wo shi nen die!";

        fd = open("./file1",O_RDWR);
        if(fd == -1)
        {
                printf("open file1 failedn");
                fd = open("./file1",O_RDWR|O_CREAT,0600);
                if(fd > 0)
                {
                        printf("creat file1 successn");
                }
        }
        printf("open success!n:fd = %dn",fd);

        int n_write = write(fd,buf,strlen(buf));
        if(n_write != -1)
        {
                printf("write %d byte to fali1n",n_write);
        }
        close(fd);
        open("file1",O_RDWR);
        char *readBuf;
        readBuf = (char *)malloc(sizeof(n_write+1));
        int n_read = read(fd,readBuf,n_write);
        printf("read %d byte context:%s",n_read,readBuf);
        close(fd);
       
        return 0;
}

因为光标位置 读取时需要关闭再打开file1,使光标移动到最前面在读取。
在这里插入图片描述
缓冲区readBuf 读取到readBuf中

四、光标的移动

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main()
{
        int fd;
        char *buf = "wo shi nen die!";
        fd = open("./file1",O_RDWR);
        if(fd == -1)
        {
                printf("open file1 failedn");
                fd = open("./file1",O_RDWR|O_CREAT,0600);
                if(fd > 0)
                {
                        printf("creat file1 successn");
                }
        }
        printf("open success!n:fd = %dn",fd);
        
        int n_write = write(fd,buf,strlen(buf));
        if(n_write != -1)
        {
                printf("write %d byte to fali1n",n_write);
        }

        lseek(fd,0,SEEK_SET);
        
        char *readBuf;
        readBuf = (char *)malloc(sizeof(n_write+1));
        int n_read = read(fd,readBuf,n_write);
        printf("read %d byte context:%s",n_read,readBuf);
        close(fd);
        return 0;
}
~   

在这里插入图片描述
SEEK_SET:光标移动到初始位置
SEEK_CUR:光标移动到当前位置
SEEK_END:光标移动到高末尾

off_t offset : 偏移大小 正数向右偏移,负数向左偏移

五、利用光标计算文件大小
在这里插入图片描述
返回值一个偏移值 from the biginning of the file

六、文件打开创建的补充

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

int main()
{
        int fd;
        fd = open("./file1",O_RDWR|O_CREAT|O_EXCL,0600);
        if(fd == -1)
        {
                printf("file1 exsitn");
        }
        return 0;
}

O_EXCL:若文件存在返回-1(如果同时指定了O_CREAT,而文件已经存在,则出错)

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main()
{
        int fd;
        char *buf = "wo shi nen die!";
        fd = open("./file1",O_RDWR|O_APPEND);
        printf("open success!n:fd = %dn",fd);

        int n_write = write(fd,buf,strlen(buf));
        if(n_write != -1)
        {
                printf("write %d byte to fali1n",n_write);
        }
        close(fd);
        return 0;
}
~       

O_APPEND:防止文件被覆盖,在其下一行继续写入(每次写时都加到文件的尾端)

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main()
{
        int fd;
        char *buf = "wo shi nen die!";
        fd = open("./file1",O_RDWR|O_TRUNC);
        printf("open success!n:fd = %dn",fd);

        int n_write = write(fd,buf,strlen(buf));
        if(n_write != -1)
        {
                printf("write %d byte to fali1n",n_write);
        }
        close(fd);
        return 0;
}

O_TRUNC:将原文件内容全部干掉重新写入

另一个创建函数 creat
在这里插入图片描述
宏表示——数字
S_IRUSE ——4-可读
S_IWUSR——2-可写
S_IXUSR——1-可执行
S_IRWXU——7-可读、可写、可执行

七、文件操作原理简述
https://baike.baidu.com/item/%E6%96%87%E4%BB%B6%E6%8F%8F%E8%BF%B0%E7%AC%A6/9809582?fr=aladdin

标准输入输出

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
        int fd;
        char readBuf[128];
        int n_read = read(0,readBuf,5);
        int n_write = write(1,readBuf,strlen(readBuf));
        printf("ndonen");
        return 0;
}

动态文件、静态文件
习惯上,标准输入(standard input)的文件描述符是 0,标准输出(standard output)是 1,标准错误(standard error)是 2.

int n_read = read(0,readBuf,5):读取5个字符到readBuf中

文件平时是存放在块设备中的文件系统文件中的,我们把这种文件叫静态文件,当我们去open打开一个文件时,Linux内核做的操作包括:内核进程中建立一个打开文件的数据结构,记录下我们打开的这个文件;内核在内存中申请一段内存,并且将静态文件的内容从块设备中读取到内核中特定地址管理存放(叫动态文件)

打开文件后,对这个文件的读写操作,都是针对内存中的这一份动态文件的,并不是针对静态文件的。当我们对动态文件进行读写以后,此时内存中动态文件和块设备中的静态文件就不同步了,当我们close关闭动态文件时,close内部内核将内存中的动态文件的内容去更新(同步)块设备中的静态文件

为什么这么设计:不直接对块设备直接操作
块设备本身非常不灵活,是按块读写的,而内存是按字节单位操作的,而且可以随机操作,很灵活

八、小应用之实现cp功能

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

int main(int argc,char **argv)
{
        int fdSrc;
        int fdDes;
        char *readBuf = NULL;
        if(argc != 3)
        {
                printf("param errorn");
                exit(-1);
        }

        fdSrc = open(argv[1],O_RDWR);
        int size = lseek(fdSrc,0,SEEK_END);
        lseek(fdSrc,0,SEEK_SET);
        readBuf = (char *)malloc(sizeof(char)*size + 8);
        int n_read = read(fdSrc,readBuf,size);

        fdDes = open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0600);
        int n_write = write(fdDes,readBuf,strlen(readBuf));

        close(fdSrc);
        close(fdDes);
        return 0;
}

}

九、配置文件的修改

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc,char **argv)
{
        int fdSrc;
        char *readBuf = NULL;
        if(argc != 2)
        {
                printf("wrongn");
                exit(-1);
        }

        fdSrc = open(argv[1],O_RDWR);
        int size = lseek(fdSrc,0,SEEK_END);
        lseek(fdSrc,0,SEEK_SET);
        readBuf = (char *)malloc(sizeof(char)*size+8);
        int n_read = read(fdSrc,readBuf,size);

        char *p = strstr(readBuf,"LENG");
        if(p==NULL)
        {
                printf("Not found");
                exit(-1);
        }

        p = p+strlen("LENG=3");
        *p = '5';
        lseek(fdSrc,0,SEEK_SET);
        int n_write = write(fdSrc,readBuf,strlen(readBuf));

        close(fdSrc);

        return 0;
}

}

strstr
在这里插入图片描述
查找 返回值是一个指针指向查找的头

十、写一个整数到文件

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

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

        fd = open("./file1",O_RDWR);

        int n_write = write(fd,&data,sizeof(int));

        lseek(fd,0,SEEK_SET);

        int n_read = read(fd,&data2,sizeof(int));

        printf("data2:%dn",data2);

        close(fd);

        return 0;
}

在这里插入图片描述
该处是一个指针数据类型,所以取地址

十一、写结构体到文件
换汤不换药,取地址,但是链表直接写入可能会出问题,链表是连续的,结构体数组是块

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

struct Test
{
        int a;
        char b;
};

int main()
{
        int fd;
        struct Test data[2] = {{99,'a'},{100,'b'}};
        struct Test data2[2];

        fd = open("./file1",O_RDWR);

        int n_write = write(fd,&data,sizeof(struct Test)*2);

        lseek(fd,0,SEEK_SET);

        int n_read = read(fd,&data2,sizeof(struct Test)*2);

        printf("data2:%dn,%cn",data2[0].a,data2[0].b);
        printf("data2:%dn,%cn",data2[1].a,data2[1].b);

        close(fd);

        return 0;
}

十二、标准C库对文件的引入
C语言第四版第十章
对于这两个名字很类似的函数,对于很多初学者来说,不容易搞清楚它们有什么不同,只知道按照函数用法使用。如果能很好的区分两者,相信大家对于C语言和UNIX系统(包括LINUX)有更深入的了解。

在网上查找了一些资料,但是感觉不够全面,一些答案只是从某个角度阐述,所以让人觉得,这个也对,那个也对。但到底谁的表述更正确呢?其实都是对的,只是解释的视角不同罢了。下面结合个人的理解做一些梳理。

  1. 来源
    从来源的角度看,两者能很好的区分开,这也是两者最显而易见的区别:

open是UNIX系统调用函数(包括LINUX等),返回的是文件描述符(File Descriptor),它是文件在文件描述符表里的索引。
fopen是ANSIC标准中的C语言库函数,在不同的系统中应该调用不同的内核api。返回的是一个指向文件结构的指针。
PS:从来源来看,两者是有千丝万缕的联系的,毕竟C语言的库函数还是需要调用系统API实现的。

  1. 移植性
    这一点从上面的来源就可以推断出来,fopen是C标准函数,因此拥有良好的移植性;而open是UNIX系统调用,移植性有限。如windows下相似的功能使用API函数CreateFile

  2. 适用范围
    open返回文件描述符,而文件描述符是UNIX系统下的一个重要概念,UNIX下的一切设备都是以文件的形式操作。如网络套接字、硬件设备等。当然包括操作普通正规文件(Regular File)。
    fopen是用来操纵普通正规文件(Regular File)的。

  3. 文件IO层次
    如果从文件IO的角度来看,前者属于低级IO函数,后者属于高级IO函数。低级和高级的简单区分标准是:谁离系统内核更近。低级文件IO运行在内核态,高级文件IO运行在用户态。

  4. 缓冲
    缓冲文件系统
    缓冲文件系统的特点是:在内存开辟一个“缓冲区”,为程序中的每一个文件使用;当执行读文件的操作时,从磁盘文件将数据先读入内存“缓冲区”,装满后再从内存“缓冲区”依此读出需要的数据。执行写文件的操作时,先将数据写入内存“缓冲区”,待内存“缓冲区”装满后再写入文件。由此可以看出,内存“缓冲区”的大小,影响着实际操作外存的次数,内存“缓冲区”越大,则操作外存的次数就少,执行速度就快、效率高。一般来说,文件“缓冲区”的大小随机器 而定。fopen, fclose, fread, fwrite, fgetc, fgets, fputc, fputs, freopen, fseek, ftell, rewind等。
    非缓冲文件系统
    缓冲文件系统是借助文件结构体指针来对文件进行管理,通过文件指针来对文件进行访问,既可以读写字符、字符串、格式化数据,也可以读写二进制数据。非缓冲文件系统依赖于操作系统,通过操作系统的功能对文件进行读写,是系统级的输入输出,它不设文件结构体指针,只能读写二进制文件,但效率高、速度快,由于ANSI标准不再包括非缓冲文件系统,因此建议大家最好不要选择它。open, close, read, write, getc, getchar, putc, putchar等。
    一句话总结一下,就是open无缓冲,fopen有缓冲。前者与read, write等配合使用, 后者与fread,fwrite等配合使用。

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

这样一总结梳理,相信大家对于两个函数及系列函数有了一个更全面清晰的认识,也应该知道在什么场合下使用什么样的函数更合适,效率更高。

十三、标准C库打开创建读写文件,光标移动

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

int main()
{
        FILE *fd;
        char *buf = "wo shi nen die";
        char readBuf[128] = {0};
        fd = fopen("./zhang.txt","w+");

        fwrite(buf,sizeof(char),strlen(buf),fd);

        fseek(fd,0,SEEK_SET);

        fread(readBuf,sizeof(char),strlen(buf),fd);

        printf("%s",readBuf);

        fclose(fd);

        return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

fd = fopen("./zhang.txt","w+");
w+ :权限 注意双引号
int write = fwrite((void *ptr, size_t size, size_t nmemb, FILE *stream);

int nread = fwrite((void *ptr, size_t size, size_t nmemb, FILE *stream);
返回值取决于第三个参数  这两个有细微的区别

十四、标准C库写结构体到文件

#include <stdio.h>
#include <string.h>
struct Test
{
        int a;
        char c;
};

int main()
{
        FILE *fd;

        struct Test data = {100,'a'};
        struct Test data2;

        fd = fopen("./file1","w+");

        fwrite(&data,sizeof(struct Test),1,fd);

        fseek(fd,0,SEEK_SET);

        fread(&data2,sizeof(struct Test),1,fd);

        printf("%d,%c",data2.a,data2.c);

        fclose(fd);

        return 0;
}

十五、补充
fputc:

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

int main()
{
        int i;
        int len;
        FILE *fp;
        char *str = "wo shi nen die";
        len = strlen(str);
        fp = fopen("./test.txt","w+");
        for(i=0;i<len,i++)
        {
        fputc(*str,fp);
        str++;
        }

        fclose(fp);
        return 0;

}

feof:判断是否到达文件的尾巴
fgetc

在这里插入图片描述
到达文件尾巴返回0

#include <stdio.h>

int main()
{
        FILE *fp;
        char c;
        fp = fopen("./test.txt","r");

        while(!feof(fp)) //!取反
        {
                c = fgetc(fp);
                printf("%c",c);
        }

        fclose(fp);

        return 0;

}

最后

以上就是喜悦往事为你收集整理的Linux系统编程 文件的全部内容,希望文章能够帮你解决Linux系统编程 文件所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(53)

评论列表共有 0 条评论

立即
投稿
返回
顶部