本文介绍5个io相关的系统调用——open、close、read、write、lseek。这5个函数被称为不带缓冲区的函数,标准C的输入输出函数就是对read和write的封装,先来看这些函数的函数原型。
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char* pathname, int flag);
int open(const char* pathname, int flag, mode_t mode);
返回值:若成功则返回文件描述符,失败则返回-1。
open函数用于打开或创建一个文件,参数pathname表示文件名,参数flag是用来说明此函数操作的参数,如果第二个参数指定了O_CREAT,即创建一个文件,那么调用第二个open函数,此时必须指定第三个参数mod,代表了创建的文件的默认权限。
flag参数常用选项:
O_RDONLY——只读打开。
O_WRONLY——只写打开。
O_RDWR——读、写打开。
O_CREAT——若文件不存在则创建。用此参数必须指定第三个参数。
O_APPEND——每次写时都追加到文件的尾端。
O_EXCL——如文件已存在则出错,常与O_CREAT联用创建一个新文件。
include <unistd.h>
int close(int fd);
返回值:若成功返回0,失败则返回-1。
close函数的参数为一个文件描述符,此函数用于关闭一个文件。
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t nbytes);
返回值:若成功返回读到的字节数,读到文件末尾返回0,出错返回-1。
read函数用于在文件描述符fd指定的文件里面读取长度为ntytes的数据到缓冲区buf中,读取数据单位是byte。
#include <unistd.h>
ssize_t write(it fd, const void *buf, size_t nbytes);
返回值:成功返回已写的字数,出错返回-1。
write函数用于向fd指定的文件中写入缓冲区buf中的nbytes字节的数据,如果要从打开文件的末尾处写入,则文件打开时必须指定O_APPEND选项。
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
返回值:若成功返回新的文件偏移量,出错返回-1。
lseek函数用于显示地设置一个打开的文件的偏移量。第一个参数fd为文件描述符,后面两个参数的关系:
上面是《UNIX环境高级编程》里面的描述。
现在在一个程序中应用这几个函数:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int fd = open("myfile", O_RDWR|O_CREAT, 0644); //以读写打开,无则创建。
if(fd < 0)
{
perror("open");
exit(EXIT_FAILURE);
}
int i = 0;
while(i++ < 10) //向文件中写入10个字符串
{
if(write(fd, "hello\n", strlen("hello\n")) < 0)
{
perror("write");
exit(EXIT_FAILURE);
}
}
lseek(fd, 50, SEEK_END); //通过lseek改变文件长度,使文件当前偏移量后移50个字节。
while(i++ < 20) //继续写入10行字符串。这样就使得两次写入的字符串中间出现一个“空洞”。
{
if(write(fd, "world\n", strlen("world\n")) < 0)
{
perror("write");
exit(EXIT_FAILURE);
}
}
char buf[1024] = { 0 };
lseek(fd, 0, SEEK_SET); //通过lseek函数使当前偏移量指向文件开始位置。
ssize_t size = 0;
while((size = read(fd, buf, sizeof(buf)-1)) > 0) //读取文件内容
{
buf[size] = 0;
if(write(1, buf, strlen(buf)) < 0) //读从文件中读出的内容进行打印。
{
perror("write");
exit(EXIT_FAILURE);
}
}
if(size < 0)
{
perror("read");
exit(EXIT_FAILURE);
}
close(fd);
return 0;
}
运行结果:
可以看到,运行程序输出了10行最开始写入文件的字符串,并创建了一个文件”myfile”,打印出myfile文件中的内容:
可以很明显的看到在文件myfile中出现一个“空洞”,这部分值被读为0,但它们所在的位置并没有值,当读出时,到达这里后就会认为已经读到了文件末尾而停止读出数据,因此运行程序在屏幕上仅打印出了10行“hello”,而没有打印出”world”。