Linux下的基础IO操作
fopen,fwrite,fread,fclose,open,write,read,close
首先我们先来回顾一下C语言下文件接口
一.打开文件
1.先说一下fopen函数,它的第一个参数path是一个通过路径指向的字符串,即文件名,第二个参数mode是采用什么方式打开该文件,具体mode的值如下
r以只读方式打开
r+方式打开可以提供读写操作
w方式只要打开一个文件,如果文件里有内容,那么将清除内容,可以理解为只写操作
w+方式打开与r+方式一样提供读写,但如果文件不存在则会创建该文件,
a以附加的方式打开,能够在文件末尾写入,如果文件不存在则会创建该文件,如果文件内有内容,想继续写内容不删除原来的内容,则a的方式可以做到
a+以读和附加的方式打开,能够在文件末尾写入,如果文件不存在则会创建该文件,最初读文件的位置在文件开头,但是写入的时候总是在文件结尾。
通常的来说,r方式和w方式用的最多,因为通常我们打开文件只要求完成一个功能。
2.对于fdopen函数,它将流与现有的文件描述符fd相关联,它的第一个参数是一个文件描述符,第二个参数流的模式(之前介绍的6种流)必须与文件描述符的模式兼容。
3.对于freopen函数,前两个参数与fopen相同,它的作用打开一个文件,并将其与流指向的流关联起来它,它的主要用途是更改与标准文本(stdout,stdin,stderr)相关联的文件。
这三个函数成功的返回值都是一个FILE* 文件指针,否则将返回NULL并将errno设置为显示错误。
二.读文件与写文件
fread和fwite函数用于读写记录,参数ptr表示用于接收数据的位置,size表示要读或写的每个记录的字节数,nmemb表示要读取nmemb个大小为size个字节的记录,这些记录在ptr中连续存放,共占用(size * nmemb)个字节,fread从文件stream中读出(size * nmemb)个字节保存到ptr中,而fwrite把ptr中的(size * nmemb)个字节写到文件stream中。
它们的返回值返回读或写的记录数,成功时返回的记录数等于nmemb,出错或到达文件末尾时返回的记录数小于nmemb,也可能返回0。
fread函数不区分文件结束和错误,我们需要调用ferror和feof来确定发生了什么。
feof函数测试流指向的流的文件尾指示符,如果设置为非零,则返回非零。
ferror函数测试流指向的流的错误指示器,如果设置为非零,则返回非零。
关于这两个函数的测试代码如下
fwrite
执行结果如下
fread
执行结果如下,这里的myfile文件是已经执行过了fwrite后已经写入了内容
三.关闭文件
关闭文件很简单,在上面的代码中也有用到,只要传一个文件指针就能够实现。
成功将返回0,否则将返回EOF,并设置error来表示错误。
另外需要说明的是,C打开文件时默认打开的三个流stdin,stdout和stderr ,这三个的类型都是FILE*,都是fopen的返回值类型,它们都是文件指针。
/*********************************************************************************************/
接下来我们看一下系统级别的I/O,也就是操作系统提供给用户的一些系统调用。同样地,我们也是从按打开文件,读写文件,关闭文件来说明。
一.打开文件
open函数有两种传参形式,这个我们稍后再说,我们先来看一下它的返回值。open函数如果调用成功返回的是一个最低编号的文件描述符,它是一个非负数,前面说过打开一个文件的时候系统会默认打开三个文件stdin,stdout,stderr,它们的对应的文件描述符分别是0,1,2,所以一般来说,在不先关闭以上三个文件的前提下,系统打开的文件对应的文件描述符应是3;如果调用不成功,则返回-1。
第一个参数是打开文件的路径名,也就是文件名。
对于第二个参数,首先它必须包含以下三个参数之一:O_RDONLY(只读), O_WRONLY(只写), or O_RDWR(可读可写),这是打开文件的方式。
此外更多的文件状态标志和文件创建标志如下:
- O_APPEND
文件在append模式中打开。在每次写入之前,文件偏移位置位于文件的末尾。如果多个进程同时向文件追加数据,那么O_APPEND可能会导致NFS文件系统上的文件损坏。这是因为NFS不支持对文件的附加,因此客户机内核必须模拟它,这是不可避免的竞态条件。 - O_ASYNC
启用信号驱动的I / O:在这个文件描述符上能输入和输出时生成一个信号(默认为SIGIO,可以通过fcntl进行更改)。该特性只适用于终端、伪终端、套接字、管道和FIFOs(匿名管道)。 - O_CLOEXEC
启用新文件描述符的close-on-exec标志。指定此标志允许程序避免额外的fcntl F_SETFD操作来设置FD_CLOEXEC标志。此外,在一些多线程程序中使用此标志是必要的,因为使用一个单独的fcntl F_SETFD操作来设置FD_CLOEXEC标志,这并不足以避免竞态条件一个线程在另一个线程执行fork和execve的同时打开一个文件描述符。 - O_CREAT
如果文件不存在,它将被创建。第三个参数mode指定在创建新文件时使用的权限。当指定O_CREAT时,必须提供这个参数;如果没有指定O_CREAT,则忽略第三个参数mode。mode的值一般用8进制的数来表示,如0666表示拥有者,所属组和其他用户对该文件的权限都是可读可写,这与权限的设置方式一样。 - O_DIRECT
尝试将I / O的缓存效果最小化到此文件。总的来说,这将降低性能,特殊情况下它是有用的,例如应用程序自己进行缓存时。文件I / O直接由用户空间缓冲区完成。I/ O是同步的,即在完成读或写时,保证数据被传输。 - O_DIRECTORY
如果路径名不是目录,则导致打开失败 - O_EXCL
确保此调用创建文件:如果此标志与O_CREAT一起指定,且路径名已经存在,那么open()将会失败。如果没有指定O_CREAT,则O_EXCL的行为是未定义的。 - O_NOATIME
当读取文件时,不要更新文件的最后访问时间(inode中的st_atime) - O_NOCTTY
如果路径名是指终端设备,即使是进程不存在,它也不会成为进程的控制终端。 - O_NOFOLLOW
如果路径名是一个符号链接,则打开失败。 - O_NONBLOCK或O_NDELAY
当可能时,文件以非阻塞模式打开。 - O_TRUNC
如果文件已经存在,并且是一个常规文件,而开放模式允许写入(即:,是O_RDWR或O_WRONLY),文件将被截断为长度0。如果文件是FIFO或终端设备文件,则忽略O_TRUNC标志。
二.读写文件
read函数的作用是从文件描述符为fd的文件中,读取count个字节的数,读到buf当中;
write函数的作用是将buf中count个字节的数写到文件描述符为fd的文件当中。
对于返回值,我们可以注意到,两个函数返回的都是ssize_t,这个类型其实是signed size_t;size_t是无符号的数据类型,二ssize_t是有符号的数据类型,也就是说它可以表示负数。
read函数调用成功时,它将返回读取的字节数。它的返回值是可能小于count的值的,主要的原因可能是我们EOF关闭了文件,或者是我们从管道或是终端在读取数据,也可能read被一个信号终止了。如果count传的是0,则read不起作用并返回0;如果函数最后返回0,表示已到达文件尾或无可读取的数据;如果调用失败,则返回的是-1。
write函数调用成功时,返回写入的字节数。否则返回-1。
read和write的测试函数如下:
write
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
umask(0);
int fd = open("myfile",O_WRONLY|O_CREAT,0666);
if(fd < 0)
{
perror("open\n");
return 1;
}
const char* buf="hello world\n";
int count=5;
while(count--)
{
ssize_t s=write(fd,buf,strlen(buf));
if(s<0)
{
perror("write\n");
}
}
return 0;
}
read
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
int fd=open("myfile",O_RDONLY);
if(fd<0)
{
perror("open!\n");
return 1;
}
char buf[1024];
const char* msg="hello world\n";
while(1)
{
ssize_t s=read(fd,buf,strlen(msg));
if(s>0)
{
printf("%s",buf);
}
else
{
break;
}
}
close(fd);
return 0;
}
三.关闭文件
这个很简单,成功返回0,失败返回-1。
更多推荐
所有评论(0)