unix-like(后面以linux为例)系统中的文件操作只需要五个函数就足够了,open、close、read、write以及lseek。这些操作被称为不带缓存的io,这里有必要说一下带缓存和不带缓存的操作的区别。不带缓存的io是相对于带缓存的io的来说的,带缓存的io有哪些呢。在后面的fwrite、fread函数等标准io操作都是带缓存的io。说了这么多还是没有说清楚带缓存和不带缓存的区别,下面就以write函数和fwrite函数来说明带缓存和不带缓存的区别。虽然write函数叫做不带缓存的io,但是当write函数向文件中写入数据时,会先将数据写入到内核的一个缓冲区中,注意这个缓冲区是由内核提供的,当内核的缓冲区填满以后,内核将缓冲区中的数据排队到输出队列的末端,然后由内核相应的功能将输出队列的数据输出到磁盘,所以write函数还是有缓冲的,我们也将write函数称作系统调用。下面介绍了fwrite函数之后就可以理解为什么write函数叫不带缓存的函数。fwrite函数是对write函数封装的结果。在封装时,在用户的层面上提供了一些缓冲区,当向文件中写入数据时,只有当用户层面的缓冲区填满时,才会将这些缓冲区中的数据写入到内核的缓冲中。这样就可以理解带缓存的io和不带缓存的io,这都是相对于用户层面而言的。

在linux系统中,为每一个打开的文件分配一个文件描述符。所有的程序都打开了三个文件,标准输入,标准输出和标准出错。这三个文件的描述符分别为0,1,2,或者分别用宏定义STDIN_FILENO、STDOUT_FILENO和STDERR_FILENO来表示。当打开一个其它非标准输入输出文件时,则返回一个系统中尚未使用的编号最小的文件描述符,当然这个描述符必定是大于或者等于3的。

open函数用来打开一个文件,它的函数原型是:

int open(const char* pathname,int oflag,...);

第一个参数是用来指定所要打开的文件的路径和名字,第二个参数用来指定文件的打开方式,第三个参数...表示后面可以有任何类型的任意多个参数,不过第三个参数只有在用open函数创建新文件时才用来指定新建文件的权限。第二个参数可以有的选择有:

O_RDONLY:以只读方式打开文件
O_WRONLY:以只写方式打开文件
O_RDWR:以可读可写的方式打开文件

实际上面的三种选择的值分别为0,1和2。在初学linux编程时比较容易犯的一个错误是,文件以可读可写方式打开时,写成如下的形式:

int fd = open("filename" , O_RDONLY | O_WRONLY);

O_RDONLY | O_WRONLY表示将两个宏按位进行或运算,所以这两个的运算就是 0 | 1 ,结果是1,也就是文件是按照只写的方式打开的,并不是按照可读可写的方式打开的。另外初学者还有一个疑惑,就是当文件以O_WRONLY只写方式打开时,能不能读呢?我当时就这么想,既然都可以向文件里面写数据了,为什么不能从文件中读呢?后来,我发现问题其实很简单,只是我将“读”理解错了,这里的读是机器读而不是人在读。显然当文件以只写的方式打开时,是不能将文件的内容从文件读到计算机中的。上面三种对文件的打开方式是互斥的,即三者只能存在其一。还有一些和上面三个参数进行搭配的选择,包括:O_APPEND、O_CREAT 、O_TRUNC 、O_EXCL 、O_NOCTTY 、O_NONBLOCK等,后面的这几个选项可以和前面的三个选择以按位或的方式并存。open函数如果调用成功,则返回打开文件的描述符,如果出错则返回-1,linux系统返回的文件描述符是系统尚未使用的最小的文件描述符。

creat函数的作用是创建一个新的文件,它的函数原型是:

int creat(const char* pathname,mode_t mode);

第一个参数用来指定要创建的文件的路径和名字,第二个参数用来指定创建文件的相关权限信息。creat创建的文件只能进行写操作,它相当于:

open("filename",WRONLY | O_TRUNC | O_CREAT,mode);

由于creat函数创建的文件只能向其中写入数据,所以如果需要读时,需要用以下的方式创建文件:

open("filename",O_RDWR | O_CREAT | O_TRUNC,mode);

creat函数如果调用成功,则返回打开文件的描述符,如果出错则返回-1。

close函数用来关闭打开的文件,它的函数原型是:

int close(int filedes);

它的参数是一个文件描述符,如果调用成功,则返回0,否则返回-1。

lseek函数用来设置文件指针的位置,它的函数原型是:

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

第一个参数为打开的文件描述符,第二个参数是相对于第三个参数的偏移量,第三个参数是一个标记。第三个参数有三种选择,分别是:

SEEK_SET:表示从文件起始位置开始
SEEK_CUR:表示从当前文件指针位置开始
SEEK_END: 表示从文件末尾开始

对于SEEK_SET来说,第二个参数偏移量只能为非负值,对于SEEK_CUR来说,第二个参数偏移量可正可负,对于SEEK_END来说,偏移量也是可正可负。如果SEEK_END,偏移量为正数时,会将文件指针,从当前文件末尾向后移动,中间掠过的位移填充为空,这种文件称为空洞文件。lseek如果成功返回,则返回当前文件指针的位移,如果出错则返回-1。在有些特殊的文件中,文件指针的位移允许为负值,所以,如果判断lseek是否执行成功,最好用返回值是否为-1来进行判断。

read函数用来从一个已打开的文件中读取文件的内容,它的函数原型是:

ssize_t read(int filedes,void* buff,size_t nbytes);

第一个参数是一个已打开的文件的描述符,第二个参数是一个缓冲区的指针,第三个参数是期望一次读出多少数据。这个函数的作用是每次将文件的内容读取到缓冲区buff中,如果执行成功,则返回所读取的实际字节数,如果失败,则返回-1,如果到达文件末尾,则返回0。

write函数用来向文件中写入数据,它的函数原型是:

ssize_t write(int filedes,const void* buff,size_t nbytes);

第一个参数是一个文件描述符,第二个参数是一个缓冲区的首地址,第三个参数是将要写到文件中的字节数。这个函数解释为向filedes中写入缓冲区buff的前nbytes个数据。如果执行成功,则返回实际写入到文件中的字节数,如果失败则返回-1。

[置顶] 文件io(一)--unix环境高级编程读书笔记的更多相关文章

  1. [置顶] 文件和目录(二)--unix环境高级编程读书笔记

    在linux中,文件的相关信息都记录在stat这个结构体中,文件长度是记录在stat的st_size成员中.对于普通文件,其长度可以为0,目录的长度一般为1024的倍数,这与linux文件系统中blo ...

  2. unix环境高级编程-读书笔记与习题解答-第一篇

    从这周开始逐渐的进入学习状态,每天晚上都会坚持写c程序,并且伴随对这本书的深入,希望能写出更高质量的读书笔记和程序. 本书的第一章,介绍了一些关于unix的基础知识,在这里我不想去讨论linux到底是 ...

  3. unix 环境高级编程 读书笔记与习题解答第四篇

    第一章 第六节 第一小节 这一章没有程序设计和API方面的深入学习,而是注重介绍了unix操作系统中的原始数据类型和系统原型函数,错误处理方面的知识. ____unistd.h____ 该文件包含了u ...

  4. unix 环境高级编程-读书笔记与习题解答-第二篇

    第四节 输入与输出 上次的笔记中写到的 open, read, write, lseek 以及close ,都是不带缓存的IO函数,这些函数都使用文件描述符进行工作. 上一篇笔记用到的 read(ST ...

  5. unix进程的环境--unix环境高级编程读书笔记

    http://blog.csdn.net/xiaocainiaoshangxiao/article/category/1800937

  6. unix环境高级编程 读书笔记

    1.上班业余时间把书下载下来,第一章读完了,但是程序只能回家运行啦!Fighting!

  7. Unix环境高级编程学习笔记——fcntl

    写这篇文正主要是为了介绍下fcntl,并将我自己在学习过程中的一些理解写下来,不一定那么官方,也有错误,希望指正,共同进步- fcntl: 一个修改一打开文件的性质的函数.基本的格式是 int fcn ...

  8. 《UNIX环境高级编程》笔记——3.文件IO

    一.引言 说明几个I/O函数:open.read.write.lseek和close,这些函数都是不带缓冲(不带缓冲,只调用内核的一个系统调用),这些函数不输入ISO C,是POSIX的一部分: 多进 ...

  9. 《UNIX环境高级编程》笔记——4.文件和目录

    一.引言 本章描述文件系统的其他特征和文件的性质.有些背景知识需要注意,例如用户ID与文件权限.文件系统等. 二.函数stat.fstat.fstatat和lstat #include <sys ...

随机推荐

  1. Remark of BLENDFUNCTION from MSDN

    Remarks When the AlphaFormat member is AC_SRC_ALPHA, the source bitmap must be 32 bpp. If it is not, ...

  2. 问自己----也是自己该怎么走的路(phper)

    1.首先看了PHP的源码API函数,对于许多口水仗的争论一笑而过,只是停留在脚本级别上的什么效率,安全...之争完全就是无稽之谈,没有深入理解API,所有的争论都是臆测和不科学的态度.你做了吗? 2. ...

  3. ARM 的Thumb状态测试

    作为一个使用ARM的学习者,有必要全面了解你的处理器内核.尽管有些内容可能在实际应用中用不到,但是“了解”还是很必要的.Thumb状态,是ARM的一个特色,但是你知道Thumb状态与ARM状态最大的区 ...

  4. cocos2d-x笔记4: TextField不能删除内容,以及我的解决办法。。。

    3.0正式版,win32下,TextField按下backspace键不能删除内容.网上搜了下,很早就有的问题了,正式版了竟然还不解决... 真心无力吐槽啊!!!这种巨大而又明显的Bug... 从昨天 ...

  5. 基于jsp+servlet图书管理系统之后台用户信息查询操作

    上一篇的博客写的是插入操作,且附有源码和数据库,这篇博客写的是查询操作,附有从头至尾写的代码(详细的注释)和数据库! 此次查询操作的源码和数据库:http://download.csdn.net/de ...

  6. Nth Digit | leetcode

    Find the nth digit of the infinite integer sequence 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ... Note: n i ...

  7. 支持HTML5 SqlLite的AndroidApp

    简介: 想要建立一个支持HTML5的Android App; 这个HTML5的程序需要使用本地存储,特别是sqllite; 用eclipse创建了一个app,这个app默认在res/layout建了两 ...

  8. JavaScript学习代码整理(二)--函数

    //JavaScript函数 //简单的求和函数 function sum(a,b) { return a + b; } //函数可以存储在变量中,也可以通过变量调用函数 x = sum(a,b); ...

  9. Sectong日志分析

    http://tech.uc.cn/?p=2866#comments http://blog.sectong.com/blog/hw_bigdata.html

  10. mybatis源码分析(3)——SqlSessionManager类

    从上图可能看出,在 mybatis中,SqlSession的实现类有两个,其中SqlSessionManager类不但实现了SqlSession接口,同时也实现了SqlSessionFactory接口 ...