文件IO学习大纲。

tech2022-09-15  84

一、文件IO学习大纲。 1、文件IO概念、文件概念、文件类型。 2、访问文件方法一  -> 系统IO  打开?/读取?/写入?/关闭? 3、系统IO文件描述符概念?文件描述符与文件的关系?文件描述符的值。 4、文件偏移量概念。 5、系统IO应用实例:LCD液晶、触摸屏。 6、系统IO另外一种访问文件的方式:内存映射。 -> 针对LCD液晶 7、访问文件方法二  -> 标准IO  打开?/读取?/写入?/关闭?  8、标准IO函数:处理字符/字符串 9、目录IO:访问目录,切换目录,读取目录,关闭目录。

二、文件IO概念? 1、什么是文件? 在linux下,一切都是文件。 除了我们平时常见的文件:1.txt/2.jpg/3.bmp/4.mp3是文件之外,linux系统还会把硬件设备当作是文件,例如:LED灯、触摸屏、LCD液晶屏幕,蜂鸣器,ADC,这些硬件设备在linux的眼中,都是文件来的。

2、什么是IO? IO      -> input/output  -> 输入/输出 文件IO  -> 对文件数据输入/输出   -> 写入数据到文件/从文件中读取数据出来。

3、如何实现文件读取/写入? 不需要用户写自定义函数,因为在linux下,已经有现成的函数来实现。

访问文件方式有两种: 系统IO  -> 系统调用  ->  2   System calls  -> 系统IO接口都是在第2手册。 标准IO  -> 库调用    ->  3   Library calls -> 标准IO接口都是在第3手册。   4、使用系统IO与标准IO访问有什么区别? 系统IO来处理文件,没有缓冲区,直接按字节来处理。 标准IO来处理文件,有缓冲区,按块来处理。

作用对象: 访问硬件设备文件时(LED灯、触摸屏、LCD液晶)  -> 直接使用系统IO来处理。 例如: 写一个温湿度传感器驱动   -> 使用系统IO来访问温湿度传感器驱动

访问普通文件(1.txt/2.bmp/3.jpg/4.mp3)  -> 标准IO来处理。 例如:访问test.txt这个文件               -> 使用标准IO来访问。

5、文件类型。  -> 7种。 '-'   普通文件   -> 标准IO 'd'   目录文件   -> 目录IO 'l'   链接文件    'p'   管道文件   -> 系统IO 's'   套接字文件  'c'   字符设备文件 -> 系统IO 'b'   块设备文件   -> 系统IO

三、如何使用系统IO访问文件? 1、如何打开文件?  -> open()   -> man 2 open 函数功能:open and possibly create a file      //打开和创建文件。

头文件:     #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);

参数:     pathname:需要打开的那个文件的路径名。 (绝对路径/相对路径)     flags:          O_RDONLY:只读          O_WRONLY:只写          O_RDWR:可读可写

返回值:     成功:新的文件描述符file descriptor(其实就是一个最小,非负整数,没有使用过的)     失败:-1

注意:open函数什么时候会打开失败? 1)你打开的路径不存在时。 2)如果文件本身的权限不允许,那么操作权限不对,也会失败。    例如: 文件本身的权限: "-wx-wx-wx",如果以O_RDONLY/O_RDWR去打开文件,那么就会失败。

2、如何关闭文件?  -> close()  -> man 2 close 函数功能:close a file descriptor     //关闭掉一个文件描述符

头文件:      #include <unistd.h>

函数原型:     int close(int fd);

参数:     fd:需要关闭的那个文件的文件描述符。

返回值:     成功:0     失败:-1

  练习1: 写程序,访问家目录下test.txt,如果访问成功,则输出"open file success",否则输出"open file error",并关闭文件,如果关闭成功,则输出"close file success",否则输出"close file error"。

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

int main(int argc,char *argv[]) {     int fd,ret;     fd = open("/home/gec/test.txt",O_RDWR);     if(fd >= 0)     {         printf("open file suceess!\n");     }     else{         printf("open file error!\n");     }     printf("fd = %d\n",fd);          ret = close(fd);     if(ret == 0)     {         printf("close file success!\n");     }     else{         printf("close file error!\n");     }          return 0; }

  练习2: 看看访问之后的那个文件的文件描述符是多少?  -> 3   练习3: 尝试访问一下开发板中/dev/fb0这个文件,访问之后就关闭它。     #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h>

int main(int argc,char *argv[]) {     int fd;     fd = open("/dev/fb0",O_RDWR);     if(fd < 0)     {         printf("open file error!\n");     }          close(fd);          return 0; }

四、文件描述符? 1、什么是文件描述符? 文件描述符是open函数的返回值,当open()执行成功时,就会返回非负,最小,没有使用过的整数。 例如: 3=open("1.txt");  //3就是代表这个1.txt这个文件。 4=open("2.txt");  //4就是代表这个2.txt这个文件。 A105=open("关国源")  //A105就是代表这个关国源这个文件。

结论:将来需要处理文件时,我们不需要提供文件名字,只需要提供文件对应的文件描述符就可以。

2、访问文件时,发送fd从3开始分配,说明0/1/2已经被占用,究竟是谁在占用? 其实在系统启动时,就会默认打开3个文件,分别是"标准输入","标准输出","标准出错",他们其实是一个宏定义来的,是被定义在一个头文件中,头文件路径:/usr/include/unistd.h

/* Standard file descriptors.  */ #define    STDIN_FILENO    0    //标准输入  -> 对象:键盘 #define    STDOUT_FILENO    1    //标准输出  -> 对象:屏幕 #define    STDERR_FILENO    2    //标准出错  -> 对象:屏幕

  可以理解: 只要系统启动, 0 = open("标准输入")

3、举例子。 假设当前目录下有:a.txt b.txt c.txt d.txt 打开a.txt 打开b.txt 打开c.txt 关闭b.txt 打开d.txt 关闭a.txt 关闭c.txt 打开a.txt 打开c.txt 关闭d.txt 打开d.txt  -> 返回值是多少?    --> 4

  结论:打开一个文件时候,就会得到一个文件描述符。                 -> 申请资源         关闭一个文件时候,这个文件对应的文件描述符就可以被别人使用。-> 释放资源

4、研究文件描述符有没有最大值? #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>

int main(int argc,char *argv[]) {     int fd;     while(1)     {         fd = open("./a.txt",O_RDWR);         printf("fd = %d\n",fd);         if(fd == -1)         {             break;         }     }     return 0; }

范围:0~1023。 记住:打开文件之后,记得要关闭!

五、open函数的拓展参数。

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

pathname:需要打开的文件的路径 flags: 必选(三选一) O_RDONLY:只读 O_WRONLY:只写 O_RDWR:可读可写

可选(0个/多个)  -> 如果选了,就是使用了位或"|"来添加。 O_APPEND:以追加的方式打开文件,在每一次写数据之前,文件的定位都是在末尾。 O_CREAT:如果文件不存在,就会创建。     如果flags中有O_CREAT,那么mode这个参数就一定要填。     如果flags中没有O_CREAT,那么mode这个参数就算你填了,也没用。      O_TRUNC:如果文件存在并且是一个普通文件,而且打开方式必须是O_RDWR/O_WRONLY,那么这个文件就会被清空。

  例子1:测试O_CREAT是否能创建文件。

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

int main(int argc,char *argv[]) {     umask(0000);          int fd;     fd = open("/home/gec/ggy_test.txt",O_RDWR|O_CREAT,0777);     if(fd < 0)     {         printf("open error!\n");     }          close(fd);          return 0; }

如果文件是存在的: O_CREAT        -> 不创建,打开成功 O_CREAT|O_EXCL -> 不创建,打开失败   O_EXCL就是要确保O_CREAT这个参数创建了才会生效!

如果文件是不存在的: O_CREAT        -> 创建文件并且打开成功 O_CREAT|O_EXCL -> 创建文件并且打开成功

  例子2: 测试O_TRUNC能不能清空?

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

int main(int argc,char *argv[]) {     umask(0000);          int fd;     fd = open("./a.txt",O_RDWR|O_TRUNC);     if(fd < 0)     {         printf("open error!\n");     }          close(fd);          return 0; }

一般地,O_CREAT|O_TRUNC 连用,会有什么效果? 100%确保运行之后文件是存在的,并且是空白的!

 

最新回复(0)