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. php随机生成福彩双色球号码

    发布:thebaby   来源:net     [大 中 小] 不瞒您说,俺也是个双色球爱好者,经常买,但迟迟没有中过一等奖,哈哈.这里为大家介绍用php随机生成福彩双色球号码的二种方法,供朋友们学习 ...

  2. 表格行变换顺序功能(jquery)

    周末写了个更改表格行顺序的小功能,直接贴代码 表格部分如下: <table class="table" id="test_table"> <t ...

  3. c#反射机制判断同一个类的两个实例的值是否完全一样

    ; i < properties1.Length; i++)            {                string s = properties1[i].DeclaringTyp ...

  4. C#读取Excel几种方法的体会

    (1) OleDb: 用这种方法读取Excel速度还是非常的快的,但这种方式读取数据的时候不太灵活,不过可以在 DataTable 中对数据进行一些删减修改 这种方式将Excel作为一个数据源,直接用 ...

  5. java MYSQL做分页

    MySql中查询语句实现分页功能 语句: select * from 表名 where 条件 limit 要找第几页,每页多少行; import java.util.*; import java.sq ...

  6. iOS代码规范文档

    文件命名规范: 1. 项目统一使用类前缀ZY. 2. 分类命名+后面统一使用ZYExtension,例:NSDictionary+ZYExtension.h,常用分类定义在内部并写好文档注释.如果功能 ...

  7. Java编程规范整理

    分享一份网友整理的编程过程中的命名规范 包命名 包名按照域名的范围从大到小逐步列出,恰好和Internet上的域名命名规则相反. 由一组以"."连接的标识符构成,通常第一个标识符为 ...

  8. No Hibernate Session bound to thread, and configuration does not allow creat

    No Hibernate Session bound to thread, and configuration does not allow creat 今天遇到这么一个错误,在网上差了很多都没有能解 ...

  9. bzoj 3858: Number Transformation 暴力

    3858: Number Transformation Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 82  Solved: 41[Submit][Sta ...

  10. Android之单复选框及Spinner实现二级联动

    一.基础学习 1.图形学真的很神奇啊....查了些资料做出了3D云标签,哈哈...其实直接拿来用的,我们要效仿鲁迅先生的拿来主义,嘿嘿~~3D标签云就是做一个球面,然后再球面上取均匀分布的点,把点坐标 ...