6.3 不带缓存的文件I/O 操作

本节主要介绍不带缓存的文件I/O 操作,主要用到5 个函数:open、read、write、lseek和close。这里的不带缓存是指每一个函数都只调用系统中的一个函数。这些函数虽然不是ANSI C的组成部分,但是是POSIX 的组成部分。

6.3.1 open和close

(1)open和close函数说明

open函数是用于打开或创建文件,在打开或创建文件时可以指定文件的属性及用户的权限等各种参数。

close函数是用于关闭一个打开文件。当一个进程终止时,它所有已打开的文件都由内核自动关闭,很多程序都使用这一功能而不显示地关闭一个文件。

(2)open和close函数格式

open函数的语法格式如表6.1 所示。

表6.1 open函数语法要点

所需头文件

#include <sys/types.h> // 提供类型pid_t的定义

#include <sys/stat.h>

#include <fcntl.h>

续表

函数原型:int open(const char *pathname,flags,int perms)

pathname 被打开的文件名(可包括路径名)

flag:文件打开的方式

O_RDONLY:只读方式打开文件

O_WRONLY:可写方式打开文件

O_RDWR:读写方式打开文件

O_CREAT:如果该文件不存在,就创建一个新的文件,并用第三个参数为其设置权限

O_EXCL:如果使用O_CREAT时文件存在,则可返回错误消息。这一参数可测试文件是否存在

O_NOCTTY:使用本参数时,如文件为终端,那么终端不可以作为调用open()系统调用的那个进程的控制终端

O_TRUNC:如文件已经存在,并且以只读或只写成功打开,那么会先全部删除文件中原有数据

O+APPEND:以添加方式打开文件,在打开文件的同时,文件指针指向文件的末尾

函数传入值

perms 被打开文件的存取权限,为8进制表示法

函数返回值

成功:返回文件描述符

失败:-1

在 open函数中,flag参数可通过“|”组合构成,但前3 个函数不能相互组合。perms 是

文件的存取权限,采用8 进制表示法,相关内容读者可参见第2章。

close函数的语法格式如下表6.2 所示。

表6.2 close函数语法要点

所需头文件#include <unistd.h>

函数原型:int close(int fd)

函数输入值fd:文件描述符

函数返回值0:成功

-1:出错

(3)open和close函数使用实例

下面实例中的open 函数带有3 个flag 参数:O_CREAT、O_TRUNC 和O_WRONLY,

这样就可以对不同的情况指定相应的处理方法。另外,这里对该文件的权限设置为0600。其源码如下所示:

/*open.c*/

#include <unistd.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <stdlib.h>

#include <stdio.h>

int main(void)

{

int fd;

/*调用open函数,以可读写的方式打开,注意选项可以用“|”符号连接*/

if((fd = open("/tmp/hello.c", O_CREAT | O_TRUNC | O_WRONLY , 0600 ))<0){

perror("open:");

exit(1);

}

else{

printf("Open file: hello.c %d\n",fd);

}

if( close(fd) < 0 ){

perror("close:");

exit(1);

}

else

printf("Close hello.c\n");

exit(0);

}

[root@(none)1]# gcc open.c -o open

[root@(none) 1]# ./open

Open file: hello.c 3

Close hello.c

[root@(none) tmp]# ls -l |grep hello.c

-rw------- 1 root root 0 Dec 4 00:59 hello.c

经过交叉编译后,将文件下载到目标板,则该可执行文件运行后就能在目录/tmp下新建一个hello.c的文件,其权限为0600。

注意

open函数返回的文件描述符一定是最小的未用文件描述符。由于一个进程在启动时自动打开了0、1、2 三个文件描述符,因此,该文件运行结果中返回的文件描述符为3。读者可以尝试在调用open函数之前,加依据close(0),则此后在open函数时返回的文件描述符为0(若关闭文件描述符1,则在执行时会由于没有标准输出文件而无法输出)。

6.3.2 read、write和lseek

(1)read、write和lseek函数作用

read函数是用于将指定的文件描述符中读出数据。当从终端设备文件中读出数据时,通常一次最多读一行。

write函数是用于向打开的文件写数据,写操作从文件的当前位移量处开始。若磁盘已满或超出该文件的长度,则write函数返回失败。

lseek函数是用于在指定的文件描述符中将文件指针定位到相应的位置。

(2)read和write函数格式

read函数的语法格式如下表6.3 所示。

表6.3 read函数语法要点

所需头文件#include <unistd.h>

函数原型: ssize_t read(int fd,   void *buf,   size_t count)

fd文件描述符

buf指定存储器读出数据的缓冲区

count指定读出的字节数

函数返回值

成功:读到的字节数

0:已到达文件尾

-1:出错

在读普通文件时,若读到要求的字节数之前已到达文件的尾部,则返回的字节数会小于希望读出的字节数。

write函数的语法格式如下表6.4 所示。

表6.4 write函数语法要点

所需头文件#include <unistd.h>

函数原型:ssize_t write(int fd,void *buf,size_t count)

fd文件描述符

buf指定存储器写入数据的缓冲区

count指定读出的字节数

函数返回值

成功:已写的字节数

-1:出错

在写普通文件时,写操作从文件的当前位移处开始。

lseek函数的语法格式如下表6.5 所示。

表6.5 lseek函数语法要点

所需头文件

#include <unistd.h>

#include <sys/types.h>

函数原型:off_t lseek(int fd,   off_t offset,   int whence)

fd文件描述符

offset:偏移量,每一读写操作所需要移动的距离,单位是字节的数量,可正可负(向前移,向后移)

续表

SEEK_SET:当前位置为文件的开头,新位置为偏移量的大小

SEEK_CUR:当前位置为文件指针的位置,新位置为当前位置加上偏移量

whence当前位置的基点SEEK_END:当前位置为文件的结尾,新位置为文件的大小加上偏移量的大小

函数返回值

成功:文件的当前位移

-1:出错

(3)函数使用实例

该示例程序首先打开上一节中创建的文件,然后对此文件进行读写操作(记得要将文件打开属性改为可读写,将文件权限也做相应更改)。接着,写入“Hello! I'm writing to this file!”,此时文件指针位于文件尾部。接着在使用lseek 函数将文件指针移到文件开始处,并读出10个字节并将其打印出来。程序源代码如下所示:

/*write.c*/

#include <unistd.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#define MAXSIZE

int main(void)

{

int i,fd,size,len;

char *buf="Hello! I'm writing to this file!";

char buf_r[10];

len = strlen(buf);

/*首先调用open函数,并指定相应的权限*/

if((fd = open("/tmp/hello.c", O_CREAT | O_TRUNC | O_RDWR,0666 ))<0){

perror("open:");

exit(1);

}

else

printf("open file:hello.c %d\n",fd);

/*调用write函数,将buf中的内容写入到打开的文件中*/

if((size = write( fd, buf, len)) < 0){

perror("write:");

exit(1);

}

else

printf("Write:%s\n",buf);

/*调用lsseek函数将文件指针移到文件起始,并读出文件中的10个字节*/

lseek( fd, 0, SEEK_SET );

if((size = read( fd, buf_r, 10))<0){

perror("read:");

exit(1);

}

else

printf("read form file:%s\n",buf_r);

if( close(fd) < 0 ){

perror("close:");

exit(1);

}

else

printf("Close hello.c\n");

exit(0);

}

[root@(none) 1]# gcc write.c -o write

[root@(none) 1]# ./write

open file:hello.c 3

Write:Hello! I'm writing to this file!

read form file:Hello! I'm

Close hello.c

[root@(none) 1]# cat /tmp/hello.c

Hello! I'm writing to this file!

Leave a Reply

Your email address will not be published.