I/O操作
一、基本I/O操作(基于文件描述符的不带缓存的低级I/O操作)
Linux的输入/输出操作,通常为5个方面:
打开(open),读取(read),写入(write),定位(lseek),关闭(close)
文件描述符(file descriptor):
一个非负的整数,它是一个索引值,并指向内核中每个进程打开文件的记录表。
1、open函数
函数原型:int open(char * pathname, int flags)
int open(char * pathname, int flags, mode_t mode)
pathname: 表示被打开的文件名称,可以包含路径
flags: 为一个或多个标志,表示文件的打开方式
mode: 被打开文件采取的权限模式
函数返回值:成功则返回文件描述符,出错返回-1
flags:(falgs参数可通过“|”组合构成,只读、只写、读写 这三种方式是互斥的,不可同时使用)
O_RDONLY(只读方式打开),
O_WRONLY(只写方式打开),
O_RDWR(读/写方式打开),
O_CREAT(如果文件不存在,就创建新的文件),
O_EXCL(如果使用O_CREAT时,文件存在,则可返回错误信息),
O_TRUNC(如果文件已存在,且以只读或只写方式打开,则先删除文件中的原有数据),
O_APPEND(以添加方式打开文件,在打开文件的同时,文件指针指向文件末尾)
为了防止对文件的意外操作,往往要以合适的方式打开文件(只读,只写),每个文件只负责一个特定的用
途,有利于提高这些文件的重复利用。
mode:
S_IRWXU | 00700 (属主用户读写和执行权限)
S_IRUSR | 00400 (属主用户读权限)
S_IWUSR | 00200 (属主用户写权限)
S_IXUSR | 00100 (属主用户执行权限)
S_IRWXG | 00070 (属组用户读写和执行权限)
S_IRGRP | 00040 (属组用户读权限)
S_IWGRP | 00020 (属组用户写权限)
S_IXGRP | 00010 (属组用户执行权限)
S_IRWXO | 00007 (其他用户读写和执行权限)
S_IROTH | 00004 (其他用户读权限)
S_IWOTH | 00002 (其他用户写权限)
S_IXOTH | 00001 (其他用户执行权限)
2、read和write函数
read和write函数原型:ssize_t read(int fd, void * buf, size_t count)
ssize_t write(int fd, const void * buf, size_t count)
fd: 文件描述符
buf: 指定存储器读出/写入数据的缓冲区
count:指定读出或写入的字节数
函数返回值:
发生错误,返回-1,同时设置errno变量为错误代码。
操作成功,则返回值是实际读取或写入的字节数,这个字节数可能小于要求的字节数count,对于读
操作——所剩字节数少于count时,出现这种情况;写操作——磁盘已满或其它问题时出现这种情况。
在使用这两个函数时应该尽量采取块读/写的方式,提高I/O的效率
3、close函数(close会让缓冲区中的数据写回磁盘,并释放文件所占用的资源)
close函数原型:int close(int fd)
fd:文件描述符
函数返回值:文件顺利关闭,返回0;发生错误返回-1,并置errno。
示例:#include
#include
#include
#include
#include
int main(void){
int fd,size;//fd:文件描述符,用于判断打开|新建文件是否成功,size:读取到的字节数
char s[] = "hello";//需要写入的字符串
char buffer[80];//存储读出数据的缓冲区
fd = open("test.txt", O_WRONLY | O_CREAT);//以只写方式打开文件,若不存在则创建文件
if (fd == -1){
printf("Open or create file failed.\n");
return -1;
}
write(fd, s, sizeof(s));//像该文件写入字符串
close(fd);
fd = open("test.txt", O_RDONLY);//以只读方式打开文件
if (fd == -1){
printf("Open file failed.\n");
return -1;
}
size = read(fd, buffer, sizeof(buffer));//读取文件内容到buffer并返回读取的字符个数
close(fd);
printf("%s", buffer);
return 0;
}
二、基于流缓冲的标准I/O操作
1、fopen函数
打开文件有三个标准函数:FILE * fopen(const char * pathname, const char * type)
FILE * freopen(const char * pathname, const char * type, FILE * fp)
FILE * fdopen(int filedes, const char * type)
它们以不同的模式打开文件,并返回一个指向文件流的FILE指针,此后对文件读/写都是通过这个FILE指针来
进行的。以下仅介绍fopen函数。
mode:(mode字符串中带有b字符的表示打开的文件是二进制的文件)
R/rb:打开只读文件(该文件必须存在)
R+/r+b:打开可读/写的文件(该文件必须存在)
W/wb:打开只写文件,若该文件存在,则长度清为0,否则建立该文件
w+/w+b:打开可读/写文件,若该文件存在,则长度清为0,否则建立该文件
a/ab:以追加的方式打开可读/写文件,若文件存在,则在文件尾部追加数据,不修改文件原有数据,
否则新建文件。
a+/a+b:以追加的方式打开只写文件,若文件存在,则在文件尾部追加数据,不修改文件原有
数据,否则新建文件。
fopen函数可以指定打开文件的路径和模式,fdopen函数会将参数fd的文件描述符转换为对应的文件制针后返
回。freopen函数会将已打开的文件stream关闭后,打开参数path的文件。
2、fclose函数(将缓冲区的数据写入文件并释放系统所提供的文件资源)int fclose(FILE * fp)
仅将缓冲区的数据写入文件可使用fflush函数:int fflush(FILE * fp)
3、fread和fwrite函数size_t fread(void * ptr, size_t size, size_t nmemb, FILE * stream)
size_t write(const *ptr, size_t size, size_t nmemb, FILE * stream)
size: 一条记录的长度
nmemb: 指出要读或写多少条记录
返回值:读或写的记录数,成功时返回的记录数等于nmemb,出错或读到文件末尾时返回的记录数
小于nmemb也可能返回0.
这里读写的记录是指一串固定长度的字节,如一个int、一个结构体...
fread从文件stream中读取size * nmemb 字节保存到ptr中,
fwrite把ptr中的size * nmemb 字节写到文件stream中。
示例:struct record{
char name[10];
int age;
}
写入数据:write.c
struct record array[2] = { {"Tobey",20},{"Ack",23} };
FILE *fp = fopen("recfile",w);//以只写方式打开文件,若文件不存在则创建文件
if(fp == NULL){
...
}
fwrite(array, sizeof(struct record), 2, fp);//将array中的数据写入fp
fclose(fp);
读出数据:read.c
stuct record array[2];
FILE *fp = fopen("recfile",r);//以只读方式打开文件,文件必须存在
if(fp == NULL){
...
}
fread(array,sizeof(struct record), 2, fp);
printf("Name1: %s\tAge1: %d\n",array[0].name,array[0].age);
fclose(fp);