zoukankan      html  css  js  c++  java
  • 2019年7月24日星期三(文件io)

    . 文件IO学习大纲

    1. 文件IO概念,文件概念,文件类型..

    2. 如何在linux下系统IO访问一个文件?关闭文件?读取文件?写入文件?

    3. 文件描述符概念?研究文件描述符数值。文件描述符与文件关系?

    4. 文件偏移量

    5. 使用文件IO -> 系统IO 进行实际应用  -> LCD液晶

    6. 内存映射访问文件。

    7. 文件  -> 标准IO接口,如何访问?如何关闭?如何读取?如何写入?

    8. 标准IO一些特殊API函数

    9. 目录IO,目录检索,访问目录,切换目录,读取目录,关闭目录..

    . linux文件概念

    1. 什么是文件?

    linux下,一共有7种文件类型,连目录/硬件都属于文件。   -> 在linux下,一切都是文件。

    2. 什么是文件IO

    就是对这7种文件进行数据的输出(output)/输入(input)

    文件输入:  -> 将数据写入到文件

    文件输出:  -> 将文件的内容读取出来

    3. 如何实现文件的读取/写入?   -> 直接使用linux系统的函数接口

     手册数

      2   System calls (functions provided by the kernel)  -> 系统调用函数  -> 系统IO接口都是在2手册

      3   Library calls (functions within program libraries)  -> 库调用函数  -> 标准IO接口都是在3手册

    4. 使用系统IO来访问文件与标准IO有什么区别?

    系统IO  -> 无缓冲区  -> 有多少数据就处理多少数据

    标准IO  -> 有缓冲区  -> 一块一块数据地写/

      对象: 硬件设备  -> LCD液晶、触摸屏、LED灯  -> 系统IO

      对象: 普通文件  -> a.c b.txt c.jpg d.mp3  -> 标准IO

    . 使用系统IO来访问文件?

    1. 如何访问文件?   ->  open()   -> man 2 open

           #include <sys/types.h>

           #include <sys/stat.h>

           #include <fcntl.h>

        int open(const char *pathname, int flags);

           pathname:  需要访问的文件的路径

           flags: 操作文件的权限

                  O_RDONLY  -> 只读

                  O_WRONLY  -> 只写

                  O_RDWR    -> 可读可写

        返回值:

           成功: 新的文件描述符 >=0   最小非负没有使用过的整数

           失败: -1

    2. 如何关闭文件?  -> close()  -> man 2 close

        #include <unistd.h>

        int close(int fd);

         fd:需要关闭的文件描述符   -> 该数值一定是已经打开过的文件描述符。

       返回值:

           成功:0

           失败:-1

     练习1: 在ubuntu中建立一个新的文件叫test.txt,写一个程序访问该文件,并查看文件描述符的值,并关闭它!

    #include <sys/types.h>

    #include <sys/stat.h>

    #include <fcntl.h>

    #include <unistd.h>

    #include <stdio.h>

    int main()

    {

           int fd,ret;

           fd = open("test.txt",O_RDONLY);

           printf("fd = %d ",fd);

           ret = close(fd);

           printf("ret = %d ",ret);

           return 0;

    }

     练习2: 尝试访问板子中/dev/fb0这个文件,并关闭!

    #include <sys/types.h>

    #include <sys/stat.h>

    #include <fcntl.h>

    #include <unistd.h>

    #include <stdio.h>

    int main()

    {

           int fd,ret;

           fd = open("/dev/fb0",O_RDONLY);

           printf("fd = %d ",fd);

          

           ret = close(fd);

           printf("ret = %d ",ret);

          

           return 0;

    }

    .文件描述符?

    1. 什么是文件描述符呢?

    文件描述符是open()函数的返回值,如果open()执行成功,那么就会返回一个非负最小并且没有使用过的整型数据。

    例子: 

    3 = open("./test.txt");

    4 = open("/1.c");

    A105 = open("关国源");

    其中3和4就是文件描述符,也就是说3这个数字就代表了test.txt这个文件。4代表1.c这个文件,A105代表关国源,将来只需要操作这些数字,就等价于操作对应的文件。

    2. 访问文件时,发现fd等于3,说明012已经被占用,究竟是被谁占用了?

    其实系统在启动时,就会默认打开3个文件,分别是"标准输入"、"标准输出"、"标准出错",它们都是一个宏定义来的,是被定义在一个头文件,头文件的路径:/usr/include/unistd.h

    /* Standard file descriptors.  */

    #define  STDIN_FILENO      0     -> 标准输入   -> 对象就是键盘   ->  理解: 0 = open("键盘")

    #define  STDOUT_FILENO  1     -> 标准输出   -> 对象就是屏幕   ->  理解: 1 = open("液晶屏幕")        -> 有缓冲区

    #define  STDERR_FILENO   2     -> 标准出错   -> 对象就是屏幕   ->  理解: 2 = open("液晶屏幕错误信息") -> 无缓冲区

    练习3: 验证文件描述符特性:  非负最小并且没有使用过的整型数据

           当前目录下a.txt b.txt c.txt d.txt

            open(a.txt);

           open(b.txt);

           open(c.txt);         

           关闭b.txt;

           open("d.txt");

           关闭a.txt;

           open(b.txt);//3

           关闭c.txt;

           open(a.txt);//5

           open(c.txt);//6

           关闭d.txt;

           ? = open(d.txt); //4

      分配原则:最小并且是没有使用过的int非负整型数。

    3. 研究文件描述符的最大值?

    例子:

    #include <sys/types.h>

    #include <sys/stat.h>

    #include <fcntl.h>

    #include <stdio.h>

    int main()

    {

           int fd;

           while(1)

           {

                  fd = open("./test.txt",O_RDONLY);

                  printf("%d ",fd);

                  if(fd == -1)

                         break;

           }

           return 0;

    }

    结论:文件描述符范围:0~1023

    . open()函数拓展参数

           #include <sys/types.h>

           #include <sys/stat.h>

           #include <fcntl.h>

         int open(const char *pathname, int flags);

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

           flags: 操作文件的权限/文件的属性

    必选三选一:

    O_RDONLY  -> 只读

    O_WRONLY  -> 只写

    O_RDWR    -> 可读可写

    可选的额外参数(可选可不选)

    In  addition,  zero  or  more  file creation flags and file status flags can be bitwise-or'd in flags.

           如果使用0或者多个标志位,那么就使用"|"连接在一起。

    O_CREAT   -> 如果文件不存在,则创建该文件。   -> 需要填mode这个参数,这个参数代表新文件的权限。

                If  the  file  does not exist it will be created.

    mode  specifies  the permissions to use in case a new file is created.  This argument must be supplied when O_CREAT is specified in flags; if O_CREAT is not specified, then mode is ignored.

    O_EXCL  -> 存在则报错

              pathname already exists, then open() will fail.

    O_APPEND   -> 以追加的方式写入文件内容。  -> write()

    O_TRUNC  ->  文件存在则清空。  -> 必须三选一中只能选O_WRONLY/O_RDWR

    O_TRUNCO_CREAT一般会连用。

    练习4: 自己写代码验证O_CREAT、O_TRUNC、O_EXCL这参数。

    #include <sys/types.h>

    #include <sys/stat.h>

    #include <fcntl.h>

    #include <stdio.h>

    int main(int argc,char *argv[])

    {

           int fd;

           fd = open("./test.txt",O_RDWR|O_CREAT|O_TRUNC,0777);

           return 0;

    }

    .文件的数据IO处理  -> 读取/写入数据

    1. 读取文件的数据   -> read()  -> man 2 read

    功能: read - read from a file descriptor  -> 从文件描述符中读取数据,而不是从文件中读取

       #include <unistd.h>

      ssize_t read(int fd, void *buf, size_t count);

       fd:文件描述符

       buf: 数据缓冲区的地址

       count: 尝试从文件中读取的字节数   -> 这仅仅是一个愿望值。

      返回值:

           成功:实际读取到字节数

           失败:-1

      例题: 尝试从文件中读取一些字节出来? test.txt

    #include <sys/types.h>

    #include <sys/stat.h>

    #include <fcntl.h>

    #include <stdio.h>

    #include <unistd.h>

    #include <strings.h>

    int main(int argc,char *argv[])

    {

           int fd;

           char buf[100] = {0};

           //1. 打开文件

           fd = open("./test.txt",O_RDWR); //"yueqian"

           //2. 读取文件

           int n;

           n = read(fd,buf,5);

           printf("n = %d ",n); //5

           printf("buf = %s ",buf); //yueqi

           bzero(buf,sizeof(buf));

           n = read(fd,buf,5);

           printf("n = %d ",n);// 2

           printf("buf = %s ",buf); //an

           //3. 关闭文件

           close(fd);

           return 0;

    }

      结论:读取文件时,文件定位会随着读取字节而偏移。

    2. 写入数据到文件中  -> write()  -> man 2 write

    功能: write to a file descriptor  -> 写入数据到文件描述符中

        #include <unistd.h>

       ssize_t write(int fd, const void *buf, size_t count);

           fd: 文件描述符

          buf: 数据缓冲区

           count: 写入的字节数

      返回值:

           成功:实际写入的字节数

           失败:-1

    练习5: test.txt  -> 清空,将"helloworld"写入到文件中。

    #include <sys/types.h>

    #include <sys/stat.h>

    #include <fcntl.h>

    #include <stdio.h>

    #include <unistd.h>

    #include <string.h>

    int main()

    {

           int fd = open("test.txt",O_RDWR|O_TRUNC);

           char *p = "helloworld";

           write(fd,p,strlen(p));

           close(fd);

           return 0;

    }

    练习6: 验证write()文件偏移问题。

    #include <sys/types.h>

    #include <sys/stat.h>

    #include <fcntl.h>

    #include <stdio.h>

    #include <unistd.h>

    #include <string.h>

    int main()

    {

           char buf[100] = {0};

           int fd = open("test.txt",O_RDWR);

           read(fd,buf,2);

           printf("buf = %s ",buf);

           write(fd,"abc",3);

           bzero(buf,sizeof(buf));

           read(fd,buf,2);

           printf("buf = %s ",buf);

           close(fd);

           return 0;

    }

    练习7: 验证open()函数的O_APPEND参数。

    O_APPEND  -> 如果打开文件时使用了O_APPEND,那么打开文件之后,文件的定位在文件的末尾!

    #include <sys/types.h>

    #include <sys/stat.h>

    #include <fcntl.h>

    #include <stdio.h>

    #include <unistd.h>

    #include <string.h>

    int main()

    {

           int fd = open("test.txt",O_RDWR|O_APPEND);

           write(fd,"apple",strlen("apple"));

           close(fd);

           return 0;

    }

    . 文件偏移量

    文件偏移量就是当前文件定位,默认打开文件时,文件定位都是在最开头。

    1IO函数可以使得偏移量进行偏移。

    例子:  fd = open("test.txt");  -> 偏移量为0

           write(fd,"hello",5);    -> 偏移量为5

    2)如何使得不调用IO函数前提下偏移定位?   -> lseek()  -> man 2 lseek

    功能: reposition read/write file offset   -> 重新定位偏移量

            #include <sys/types.h>

            #include <unistd.h>

          off_t lseek(int fd, off_t offset, int whence);

           fd: 文件描述符

           offset: 偏移量的字节数

           whence: 偏移的基准点

           SEEK_SET  -> 相对于文件开头

            SEEK_CUR  -> 相对于当前的位置

            SEEK_END  -> 相对于文件的末尾

    这个几个宏是被定义在/usr/include/unistd.h

    # define SEEK_SET 0     /* Seek from beginning of file.  */

    # define SEEK_CUR      1     /* Seek from current position.  */

    # define SEEK_END      2     /* Seek from end of file.  */

           返回值:

                  成功: 返回值距离文件开头的字节数

                  失败: -1

    记住:

    1. 新打开文件定位一定是最开头。

    2. 读取文件可以导致偏移量的移动。

    3. 使用lseek()可以导致偏移量的移动。

    4. 相对于文件当前位置与相对于文件末尾是不一样的。

      练习8: 验证lseek第三个参数。

    #include <sys/types.h>

    #include <sys/stat.h>

    #include <fcntl.h>

    #include <stdio.h>

    #include <unistd.h>

    #include <string.h>

    int main()

    {

           char buf[50] = {0};

           int fd = open("test.txt",O_RDWR);

           read(fd,buf,2);

           printf("buf = %s ",buf);//he

           int ret = lseek(fd,5,SEEK_CUR);

           printf("ret = %d ",ret);//7

           //read(fd,buf,sizeof(buf));

           //printf("buf = %s ",buf);

           ret = lseek(fd,-4,SEEK_END);

           printf("ret = %d ",ret);//7

           bzero(buf,sizeof(buf));

           read(fd,buf,sizeof(buf));

           printf("buf = %s ",buf);

           return 0;

    }

  • 相关阅读:
    后端指路手册(建议收藏):一文告诉你后端都要学习什么?应该从哪里学起!
    《Java 编程思想四》最新中文版,附下载地址!
    大厂面试必问的 4 大开源框架,你真的就懂了吗?
    借花献佛!朋友干了5年整的Java面试官,给我分享了一份面试官最爱问的Java面试题
    字节跳动总结的设计模式 PDF 火了,完整版开放下载!
    java
    java
    java
    java
    关于public class
  • 原文地址:https://www.cnblogs.com/zjlbk/p/11239894.html
Copyright © 2011-2022 走看看