【Linux基础】文件IO

说明

参考:《UNIX环境高级编程》中文版第三版

编程环境:OS X 10.11.5  Xcode 7.3.1

文件I/O

下面介绍各类文件I/O操作。

#include <fcntl.h>
int open(const char * path, int oflag, ...);
int openat(int fd, const char * path, int oflag, ...);

用于打开或者创建文件(创建文件时需要注意flag必须有O_CREAT这个选项,并指定访问权限(通过后面的不定参数)),成功返回文件描述符,它是一个非负整数,失败返回-1。

path是需要打开或者创建的文件的名字。如果path是绝对路径,open()和openat()没有区别,openat()中的fd参数无效。如果path是相对路径,对于openat(),fd参数指定了起始路径,fd也是个文件描述符,它通过打开相对路径所在的目录来获得;对于open(),则指定当前目录为起始路径。

oflag是一系列的选项,确定打开方式,如只读、只写、读写等等:

#define O_ACCMODE	   0003
#define O_RDONLY	     00
#define O_WRONLY	     01
#define O_RDWR		     02
#define O_CREAT		   0100	/* not fcntl */
#define O_EXCL		   0200	/* not fcntl */
#define O_NOCTTY	   0400	/* not fcntl */
#define O_TRUNC		  01000	/* not fcntl */
#define O_APPEND	  02000
#define O_NONBLOCK	  04000
#define O_NDELAY	O_NONBLOCK
#define O_SYNC		 010000
#define FASYNC		 020000	/* fcntl, for BSD compatibility */
#define O_DIRECT	 040000	/* direct disk access hint */
#define O_LARGEFILE	0100000
#define O_DIRECTORY	0200000	/* must be a directory */
#define O_NOFOLLOW	0400000 /* don't follow links */
#define O_NOATIME	01000000

下面是一个例子:

#include <stdio.h>
#include <fcntl.h>

#define	FILE_MODE	(S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)

int main()
{
    int fd = 0;
    if( (fd = open("open_test", O_RDWR | O_CREAT, FILE_MODE)) != -1 )
    {
        printf("open file fd: %d\n", fd);
    }
    else
    {
        printf("open file failed\n");
    }
    return 0;
}

执行结果:

open file fd: 3
Program ended with exit code: 0

上例中创建文件的方式可以用另外一个函数来代替:

#include <fcntl.h>
int creat(const char * path, mode_t mode);

成功时返回文件描述符,失败时返回-1。它相当于:

open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);

关于mode_t,它表示的是文件的访问权限,有如下的值:

/* File mode */
/* Read, write, execute/search by owner */
#define	S_IRWXU		0000700		/* [XSI] RWX mask for owner */
#define	S_IRUSR		0000400		/* [XSI] R for owner */
#define	S_IWUSR		0000200		/* [XSI] W for owner */
#define	S_IXUSR		0000100		/* [XSI] X for owner */
/* Read, write, execute/search by group */
#define	S_IRWXG		0000070		/* [XSI] RWX mask for group */
#define	S_IRGRP		0000040		/* [XSI] R for group */
#define	S_IWGRP		0000020		/* [XSI] W for group */
#define	S_IXGRP		0000010		/* [XSI] X for group */
/* Read, write, execute/search by others */
#define	S_IRWXO		0000007		/* [XSI] RWX mask for other */
#define	S_IROTH		0000004		/* [XSI] R for other */
#define	S_IWOTH		0000002		/* [XSI] W for other */
#define	S_IXOTH		0000001		/* [XSI] X for other */

关闭文件使用的函数:

#include <unistd.h>
int close(int fd);

需要注意使用了不同的头文件。成功时返回0,出错时返回-1。

#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);

lseek()显式地为一个打开文件设置偏移量。

通常,读写操作都从当前文件偏移量开始。

默认情况下,当打开一个文件时,除非指定了O_APPEND选项,否则该偏移量被设置为0。

fd表示文件描述符,对应特定的文件。

offset和whence配合使用:

1)whence是SEEK_SET时,设置偏移量为从文件开始处offset个字节;

2)whence是SEEK_CUR时,设置偏移量为从文件当前偏移位置开始处offset个字节,offset可正可负;

3)whence是SEEK_END时,设置偏移量为文件长度加offset个字节,offset可正可负。

成功时,返回新的文件偏移量;出错时返回-1。

下面是获取当前文件偏移量的一个方法:

off_t offset = lseek(fd, 0, SEEK_CUR);
printf("offset : %lld\n", offset);

注意,lseek只负责记录文件偏移量,并不会引起任何的I/O操作。

下面两个函数才是具体的I/O操作:

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t nbytes);
ssize_t write(int fd, const void *buf, size_t nbytes);

read()成功返回读到的字节,它小于等于nbytes;失败返回-1。

write()成功返回写入的字节;失败返回-1。

一个完整的示例:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

#define	FILE_MODE	(S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)

int main()
{
    int fd;
    off_t offset;
    char *tmp = "hello world";
    char s[20] = {0};
    
    if( (fd = open("open_test", O_RDWR | O_CREAT, FILE_MODE)) != -1 )
    {
        printf("open file fd: %d\n", fd);
    }
    else
    {
        printf("open file failed\n");
        return 1;
    }
    
    offset = lseek(fd, 0, SEEK_CUR);
    printf("offset : %lld\n", offset);
    
    if( 12 == write(fd, tmp, 12))
    {
        printf("write file success\n");
    }
    
    if ( (0 == lseek(fd, 0, SEEK_SET)) && (read(fd, &s, 100) != -1) )
    {
        printf("read from file: %s\n", s);
    }
    
    close(fd);
    return 0;
}

结果:

open file fd: 3
offset : 0
write file success
read from file: hello world
Program ended with exit code: 0
#include <unistd.h>
int dup(int fd);
int dup2(int fd, int fd2);

复制一个现有的文件描述符。成功则返回新的文件描述符,失败则返回-1。

对于dup2(),如果fd2已经打开,则先关闭;如果fd等于fd2,则dup2()返回fd2,而不是关闭它。

下面的例子复制了标准输出,之后再使用write写文件的话,相当于写到了标准输出上:

#include <stdio.h>
#include <unistd.h>

int main()
{
	int tmp = dup(STDOUT_FILENO);
	write(tmp, "Hello world\n", 12);
	return 0;
}
#include <fcntl.h>
int fcntl(int fd, int cmd, ...);

用于改变已经打开的文件的属性。

根据cmd的不同,fcntl()函数有不同的功能:

1)复制已有的文件描述符,功能同dup、dup2;

2)获取/设置文件描述符标志;

3)获取/设置文件状态标志;

4)获取/设置异步I/O所有权;

5)获取/设置记录锁。

#include <unistd.h>
#include <sys/ioctl.h>
int ioctl(int fd, int request, ...);

这个函数包含其他函数无法应用到的I/O操作。这里不特别介绍了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值