文件I/O

文件I/O和标准I/O的异同linux

文件IO:文件IO称之为不带缓存的IO(unbuffered I/O)。不带缓存指的是每一个read,write都调用内核中的一个系统调用。也就是通常所说的低级I/O——操做系统提供的基本IO服务,与os绑定,特定于linix或unix平台。shell

标准IO:标准I/O是ANSI C创建的一个标准I/O模型,是一个标准函数包和stdio.h头文件中的定义,具备必定的可移植性。标准IO库处理不少细节。例如缓存分配,以优化长度执行IO等。标准的IO提供了三种类型的缓存。编程

  1. API:应用程序编程接口(一种操做系统),是一些预先定义好的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工做机制的细节。
  2. fcntl.h:定义了不少宏和open,fcntl函数原型
  3. unistd.h:定义了更多的函数原型
  4. fcntl函数能够改变已经打开的文件的属性,
  • 经常使用的文件I/O函数

UNIX系统中,绝大多数的文件I/O只须要用到5个函数:open、read、write、lseek以及close。缓存

  • 文件描述符

概念:文件描述符就是用来区分一个程序打开的多个文件的。它的做用域就是当前进程,出了当前进程这个文件描述符就没有意义了。bash

它的实质是一个数字(一个非负整数),当打开一个现有的文件或者建立一个新文件的时候,内核会向进程 返回一个文件描述符。这个数字在一个进程中表示一个特定的含义,当咱们open打开一个文件时,操做系统在内存中构建了一些数据结构来表示这个动态文件,而后返回给应用程序一个数字做为文件描述符,这个数字就和咱们内存中维护这个动态文件的这些数据结构挂钩绑定上了,之后咱们应用程序若是要操做这一个动态文件,只须要用这个文件描述符进行区分。数据结构

  • cat命令

cat命令主要用来查看文件内容,建立文件,文件合并,追加文件内容等功能,能够将文件内容显示在屏幕上,固然后面还有更加详细的用法。当想查看一个文档中有什么内容的时候,使用cat能够方便查看。函数

  • 打开与关闭文件

函数open和close优化

  • open

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

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

上图为open函数所需的头文件及调用的通常形式。fd为要打开或者建立的文件名字,oflag参数为说明该函数的多个选项,常见有O_RDONLY、O_WRONLY、O_RDWR等,后面详述。spa

(1)linux中的文件描述符fd的合法范围是0或者一个正正数,不多是一个负数。
(2)open返回的fd程序必须记录好,之后向这个文件的全部操做都要靠这个fd去对应这个文件,最后关闭文件时也须要fd去指定关闭这个文件。若是在咱们关闭文件前fd丢掉了那就惨了,这个文件无法关闭了也无法读写了。操作系统

  • close

close用来关闭一个文件描述符。

#include <unistd.h>

       int close(int fd);

上图为close经常使用的调用形式及所需的头文件。

  • read函数

read从打开的文件中读函数。

#include <unistd.h>

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

ssize_t其实就是int型,经过typedef重定义的数据类型,目的为了程序具备更好的可移植性。

ssize_t为带符号int型,size_t为不带符号的int型。count是想要读取的字节数,而返回值则是实际读取的字节数。

  • write函数

调用write函数向打开的文件中写数据。

#include <unistd.h>

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

上图为头文件和调用格式。

fd为打开的文件,*buf的数据类型为void(不肯定的数据类型)。

下面经过一个简单的例子来讲明它们的用法。

1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<sys/stat.h>
  4 #include<fcntl.h>
  5 #include<unistd.h>
  6 #include<string.h>
  7 
  8 int main(int argc,char *argv[])
  9 {
 10         int fd=-1;      //fd就是file descriptor,文件描述符
 11         char buf[100]={0};
 12         char writebuf[20]="I Love linux";
 13         int ret=-1;
 14 
 15 
 16         //第一步:打开文件
 17         fd=open("1.txt",O_RDWR);
 18         if(-1 == fd)    //有时候也写成:(fd<0)
 19         {
 20                 printf("文件打开错误\n");
 21         }
 22         else
 23         {
 24                 printf("文件打开成功,fd=%d.\n",fd);
 25         }
 26 
 27         //第二步:读写文件
 28         //写文件
 29         ret=write(fd,writebuf,strlen(writebuf));
 30         if(ret<0)
 31         {
 32                 printf("write失败.\n");
 33         }
 34         else
 35         {
 36                 printf("write成功,写入了%d个字符\n",ret);
 37         }
 38         
 39         //读文件
 40         ret=read(fd,buf,12);
 41         if(ret < 0)
 42         {
 43                 printf("read失败\n");
 44         }
 45         else
 46         {
 47                 printf("实际读取了%d字节.\n",ret);
 48                 printf("文件内容是: [%s].\n",buf);
 49         }
 50 
 51         //第三步:关闭文件
 52         close(fd);
 53 
 54         return 0;
 55 }

在代码18行,经常使用-1==fd(或fd<0),而不是fd==-1,由于要是写成fd=-1,编译调试的时候很难查出错误。

11行,char buf[100]必需要进行初始化,不然里面的数值随机。

./a.out运行以后结果如上图所示,可是read函数正常运行,却得不到预期的结果。????

  • 实时查man手册

(1)当咱们写应用程序时,不少API原型都不可能记得,因此要实时查询,用man手册 (2)man 1 xx查linux shell命令,man 2 xxx查API, man 3 xxx查库函数

相关文章
相关标签/搜索