Linux环境下对于文件学习总结

一.大体认知

1.打开/创建文件
2.编辑文档
3.保存文档
4.关闭文档

二.操作系统提供的API

1.打开 open
2.读写 write/read
3.光标定位 lseek
4.关闭 close


三.参数说明

1.open函数原型

int open(const char*pathname, int flags) \\open函数
int open(const char*pathname, int flags, mode_t mode;)

2.pathname

要打开的文件名(含路径,缺省为当前路径)

3.Flags(文件模式)

1.O_RDONLY 1 只读打开
2.O_WRONLY 2 只写打开
3.O_RDWR 4 可读可写打开

4.实例分析

实例1:把单个数据写进到一个文件中
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>

int main(int argc, int **argv)//main函数原型
{
   int fd;

   int data = 100;
   int data2 = 50;

   fd = open("./link1.c",O_RDWR);//打开名为link.c的文件

   int n_write = write(fd,&data,sizeof(int)); //,其中的fd代表的是文件描述符把data的数据写进来,听过write函数。

   lseek(fd,0,SEEK_SET);//光标定位在开头位置
   int n_read = read(fd, &data2, sizeof(int));//通过read函数读取到data2数据。

   printf("read %d,\n",data2); //最后把读取到的数据存放到link.c文件中。

   close(fd);//关闭该文件

   return 0;
}

实例2.把多个数据写到一个文件中
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<sys/stat.h>
#include<unistd.h>
#include<sys/types.h>
#include<fcntl.h>


struct Test
{
     int a;
     char b;
};

int main(int argc, int **argv)
{
   int fd;

   struct Test data[2] = {{100,'a'},{101,'t'}};//给结构体赋值两个数值。
   struct Test data2[2];

   fd = open("./link1.c",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("read %d,%c\n",data2[0].a,data2[0].b); //打印第一个数据信息,后面的.a代表的是结构体包含的整数型和字符型信息
   printf("read %d,%c\n",data2[1].a,data2[1].b);//同理

   close(fd);
   
   return 0;
}

4.四个常用权限常数

当我们附带权限后,打开的文件就只能按照这种权限来操作以下三个常数中应当只指定一个。

(1)O_CREAT

若文件不存在则创建它,使用此选项时,需要同时说明第三个参数mode,用其说明该新文件的存取许可权限。

(2)O_EXCL

如果同时指定OCREAT,而文件已经存在,则出错。

(3)O_APPEND

每次写时都加到文件的尾端。

(4)O_TRUNC

属性去打开文件时,如果这个文件本来是有内容的,而且为只读或者只写成功打开,则将其长度截断为0.

(5)mode

一定是在flags中使用了O_CREAT标志,mode记录待创建的文件的访问权限


四.creat函数(创建文件)

1.函数原型

int creat(const char *filename, mode_t mode)

2.函数参数解释(filename、mode)

1.filename:要创建的文件名(包含路径、缺省为当前路径)
2.mode:创建模式(可读可写可执行)

3.宏参数

1.S_IRUSR 可读
2,.S_IWUSR 可写
3.I_XUSR 可执行
4.S_IRWXU 可读、写、执行

4.实际操作案例

//1.给一个现有的文件里面写入数据
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<sys/stat.h>
#include<unistd.h>
#include<sys/stat.h>
#include<fcntl.h>

int main()
{
    char *readBuf = "xutanghao heng ai yangyao";//写一段数据
    int  fp;

    fp = open("./xutanghao.c",O_RDWR);//打开一个文件

    if(fp == -1){//进行判断
       printf("open xutanghao.c failed\n");
       fp = open("./xutanghao.c",O_RDWR|O_CREAT,0600);//0600权限代表文件权限
       if(fp > 0){  //非负整数
            printf("creat xutanghao.c sucess!\n");
       }
     }

     printf("open success : fp = %d\n",fp);

     write(fp, readBuf, strlen(readBuf)); //read函数使用可以通过看man手册;分别是定义的变量和需要输入的数据最后就是数据长度,把需要写的信息从readBuf缓冲区里面调用出啦
     lseek(fp,0,SEEK_SET);
     read(fp, readBuf, strlen(readBuf));//同理

     printf("open data:%s\n",readBuf);
     printf("line:%d\n",__LINE__);//printf的一种调试手段,用来发现错误的

     close(fp);//关闭对文件的操作

     return 0;
}

2.//如何创建一个文件并且给新文件里面写入数据
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<sys/stat.h>
#include<unistd.h>
#include<sys/stat.h>
#include<fcntl.h>

int main()
{
        char *buf = "xutanghao heng ai yangyao";
        int  fp;

        fp = open("./xutanghao.txt",O_CREAT|O_RDWR);//执行文件打开指令,文件权限里面包括可读可写以及创建文件

        printf("creat xutanghao.txt sucess!\n",fp); //创建文件成功。

        int n_write = write(fp,buf,strlen(buf));//把要写的信息从系统缓冲区buf调用出来,strlen代表的是所需要的空间大小。
        if(n_write){
                printf("write %d byte to file\n",n_write);
        }
        
        close(fp);
        
        return 0;
}


五.文件描述符

1.对于内核而言,所有打开文件都由文件描述符引用;文件描述符是一个非负整数;当打开一个现存文件或者一个新文件时,内核向进程返回一个文件描述符;当读写一个文件时用open和creat返回的文件描述符标识文件,将其作为参数传递给read和write。


2.UNIX shell使用文件描述符0与进程的标准输入相结合文件描述符1与标准输出相结合(SIDIN_FILEND、STDOUT_FILENO、STDERR_FILENO_FILENO这几个宏代替0、1、2这几个数)。


3.文件描述符,这个数字在一个进程中表示一个特定含义,当我们open一个文件时,操作系统在内存中构建一些数据结构来表示这个动态文件,然后返回给应用程序一个数字作为文件描述符,这个数字就和我们内存中维护的动态文件的这些数据结构绑定上了,以后我们应用程序如果操作系统这个动态文件,只需要用这个文件描述符区分。


4.文件描述符的作用域是当前进程,出了这个进程文件描述符就没有任何意义。


5.open函数打开文件时,打开成功返回一个文件描述符,打开失败返回-1。


6.静态文件和动态文件概念

(1)静态文件

文件平时是存放在块设备中的文件系统文件中的,我们把这种文件叫做静态文件

(2)动态文件

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

(3)补充内容

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


7.在linux中操作文件的注意事项

(1)在linux中要操作一个文件,一般要先open打开,得到文件描述符,然后对文件进行读写操作(或其他操作),最后是close关闭文件即可。
(2)对文件操作时,一定要先打开文件,打开成功之后才能操作,如果打开失败,就不用进行后边的操作,最后读写完成后,一定要关闭文件,否则会造成文件损坏。

8.为什么不直接对块设备直接操作

块设备本身读写非常不灵活,是按块设备读写的,而内存是按字节单位操作的,而且可以随机操作。


六.Linux的光标操作

(1)lseek的使用

SEEK_SET:开头
SEEK_CUR:现在的位置
SEKK_END:末尾

(2)函数原型

//通过查看man手册就可以看到
SYNOPSIS
       #include <sys/types.h>
       #include <unistd.h>

       off_t lseek(int fd, off_t offset, int whence);//第一个参数为文件描述符,第二个参数为偏移值,第三个参数为位置

DESCRIPTION
       lseek() repositions the file offset of the open file description associated with the file descriptor fd to the argu‐
       ment offset according to the directive whence as follows:

       SEEK_SET
              The file offset is set to offset bytes.

       SEEK_CUR
              The file offset is set to its current location plus offset bytes.

       SEEK_END
              The file offset is set to the size of the file plus offset bytes.

(3)使用方法

//上面几个实例中又涉及到
 lseek(fd,0,SEEK_SET);//光标定位到开头位置

七.标准C库下对于文件操作涉及到的函数分析

1.open与fopen函数原型

int open(const char *path, int access,int mode)
//path 要打开的文件路径和名称                          

FILE *fopen(char *filename, char *mode)//其中的mode就是下面的mode所使用的权限。
//filename 文件名称

2. mode 的打开模式

千万不可和上面的mode搞混淆了
r 只读方式打开一个文本文件
rb 只读方式打开一个二进制文件
w 只写方式打开一个文本文件
wb 只写方式打开一个二进制文件
a 追加方式打开一个文本文件
ab 追加方式打开一个二进制文件
r+ 可读可写方式打开一个文本文件
rb+ 可读可写方式打开一个二进制文件
w+ 可读可写方式创建一个文本文件
wb+ 可读可写方式生成一个二进制文件
a+ 可读可写追加方式打开一个文本文件
ab+ 可读可写方式追加一个二进制文件

3.fread和fwrite函数解析

(1)函数原型

 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);

(2)fread和fwrite函数参数解释

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
***ptr:指向数据块的指针
*** size:每个数据的大小,单位为Byte(例如:sizeof(int)就是4个字节大小)
***nmemb:数据个数
***stream:文件指针

4.fread函数操作的注意事项

(1)成功时fread返回的值与nmemb相等;若小于nmemb但是大于0,则可能是到了文件末尾,不够次数;若返回0,则是文件读取错误,不满一个size的大小。
(2)因此循环读取文件的时候,while(可以判断是否大于等于0)作为条件,里面再基于feof函数判断是否到了文件末尾而退出循环。

5.实例分析

//被注释的部分是从man手册粘贴过来的原函数;通过标准C库完成文件的读写操作。
#include<stdio.h>
#include<string.h>

int main()
{
   
    //ptr buf
    //size sizeof char
    //geshu
    //which file
    //FILE *fopen(const char *pathname, const char *mode);
  
   // int fseek(FILE *stream, long offset, int whence);


    FILE *fp; //数据指针
    char *str = "xutanghao heng shuai";
    char readBuf[128] = {0};


    fp = fopen("./xutanghao.txt","w+");

   // int nwrite = fwrite(str, sizeof(char),90, fp);
    int nwrite =  fwrite(str, sizeof(char)*strlen(str),1,fp);//一定要注意这个函数的使用方法和里面参数所代表的意思
    fseek(fp,0,SEEK_SET);
    int nread = fread(readBuf, sizeof(char)*strlen(str),1, fp);
    printf("read = %d, write = %d\n",nread,nwrite);
    printf("line:%d\n",__LINE__);

    return 0;
}
      

八.类似cp指令的操作

1.文件操作思路

1.打开src.c。(相当于原有文件)
2.读取src数据到buf。
3.打开/创建des.c。(准备创建的文件)
4.将buf写入到des.c。
5.close这两个文件。

2.实例分析

//实现类似于cp指令的代码。
//首先判断是否为3个参数,计算文件大小以及给新文件需要开辟多大的空间给新文件使用,这些操作过后把光标位置定义到开头部分,最后关闭文件操作。
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>

int main(int argc, int **argv)  //argc相当于你要准备拷贝参数;里面的argv相当于字符串数组;同时去拷贝里面的数值信息
{
   int fdSrc;  //定义两个参数
   int fdDes; //Src相当于被拷贝文件,des相当于拷贝之后的文件

   char *readBuf = NULL; //让数据缓冲区为空

   if(argc != 3){  //首先判断数值个数是否为3个
       printf("parmas error\n"); //打印出来信息
       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); //强转类型;开辟空间
   memset(readBuf,'0',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;
}                                    

九.如何在文件中记录一个结构体(标准C库下)

1.思路

1.第一步首先定义一个结构体,按照fread和fwrite的用法取两个结构体的地址放入函数结构里面,由write函数得到的数据传给read函数,最后有read函数输出最后的结果;其中的data和data2就相当与data的数据写出来后在传送到data2的地址上。
2.写入一个整型数就只用写入一个变量即可
3.这个代码是在标准C库中写出来的,如果要写成一般类型只需要看一下man手册里面其他函数对应的使用凡事即可。

2.实例分析

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

struct Test
{
        int a;
        char b;
};

int main()
{
        FILE *fp;

        struct Test data[4] = {{100,'a'},{101,'t'},{123,'e'},{34234,'r'}};  //定义两个数组,并且开辟四个空间
        struct Test data2[4]; //定义第二个结构体

        fp = fopen("./link1.c","w+");

        int n_write = fwrite(&data,sizeof(struct Test),4,fp);  //将data的地址传过来

        fseek(fp,0,SEEK_SET); //光标返回到开头部分
          int n_read = fread(&data2, sizeof(struct Test),4,fp);  //将data2的地址传送过来,开辟一个结构大小的空间

        printf("read %d,%c\n",data2[0].a,data2[0].b);//打印出来获得数据
        printf("read %d,%c\n",data2[1].a,data2[1].b);
        printf("read %d,%c\n",data2[2].a,data2[2].b);
        printf("read %d,%c\n",data2[3].a,data2[3].b);

        printf("line:%d\n",__LINE__);

        fclose(fp);//关闭对文件的操作
        /*
    fclose有两个作用:
    1. 将输出缓冲区内容写到存储设备上
    2. 释放对应的资源
    如果不调用fclose,相应地,可能会造成
    1. 对文件的更改没有被记录到磁盘上
    2. 其他进程无法存取该文件中的一种或者多种后果。因此对应fopen地调用fclose是必要的
    */


        return 0;
}


总结一句话linux一切皆文件

文件系统(文件夹/文件)硬件设备、管道、数据库、socket
后续还会有补充,那里写的不好的还望大家多多指出来
师承陈立臣老师

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值