文件I/O编程
- 1、打开文件
函数open()
需要头文件:#include< sys/stat.h>
#include< fcntl.h>
函数原型:int open(const char *pathname,int flags,int perms);
函数参数:pathname:打开文件名(可以包含具体路径名)
flags:打开文件的方式,具体见下
perms:新建文件的权限,可以使用宏定义或者八进制文件权限码,具体见下
函数返回值:成功:文件描述符
失败:-1
参数2flags具体可用参数(若使用多个flags参数可以使用|组合):
O_RDONLY:以只读方式打开文件
O_WRONLY:以只写方式打开文件
O_RDWR:以可读可写方式打开文件
O_CREAT:如果文件不存在,就创建这个文件,并使用参数3为其设置权限
O_EXCL:如果使用O_CREAT创建文件时文件已存在则返回错误信息。使用这个参数可以测试文件是否已存在
O_NOCTTY:若打开的是一个终端文件,则该终端不会成为当前进程的控制终端
O_TRUNC:若文件存在,则删除文件中全部原有数据并设置文件大小为0
O_APPEND:以添加形式打开文件,在对文件进行写数据操作时数据添加到文件末尾
注意:O_RDONLY与O_WRONLY与O_RDWR三个参数互斥,不可同时使用
若在参数2的位置有多个参数进行组合,注意使用按位或(|)运算符。
/* 可查看/usr/include/i386-linux-gnu/bits/fcntl.h文件看到具体的宏定义 */
参数3perms表示新建文件的权限,可以使用宏定义或八进制文件权限码。其中宏定义的格式是:S_I(R/W/X)(USR/GRP/OTH),其中R/W/X代表可读/可写/可执行,USR/GRP/OTH代表文件所有者/文件组/其他用户。例如:
S_IRUSR|S_IWUSR表示设置文件所有者具有可读可写权限,即0600。(一般情况下该参数都直接使用八进制文件权限码因为使用宏定义的形式太复杂)。
- 2、关闭文件
函数close()
需要头文件:#include< unistd.h>
函数原型:int close(int fd);
函数参数:fd:文件描述符
函数返回值:成功:0
失败:-1
示例:使用open()与close()打开文件和关闭文件
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/stat.h>
#include<fcntl.h>
int main()
{
int fd;
if((fd=open("hello.txt",O_RDWR|O_CREAT|O_TRUNC,0666))<0)
{
perror("fail to open file");
exit(0);
}
close(fd);
return 0;
}
以下在标准I/O中打开文件的模式所对应的在文件I/O中的模式(即flags的参数组合),其中文件名使用命令行传参的形式
r —–> open(argv[1],O_RDONLY)
r+ —-> open(argv[1],O_RDWR)
w —–> open(argv[1],O_WRONLY|O_CREAT|O_TRUNC,0666)
w+ —-> open(argv[1],O_RDWR|O_CREAT|O_TRUNC,0666)
a —–> open(argv[1],O_WRONLY|O_CREAT|O_APPEND,0666)
a+ —-> open(argv[1],O_RDWR|O_CREAT|O_APPEND,0666)
- 3、文件读写
函数read()
需要头文件:#include< unistd.h>
函数原型:int read(int fd,void *buf,size_t count);
函数参数:fd:文件描述符
buf:读取出的数据存放的缓冲区
count:指定读取的字节数
函数返回值:成功:读到的字节数 或 0(表示文件已结尾)
失败:-1
函数write()
需要头文件:#include< unistd.h>
函数原型:ssize_t write(int fd,void *buf,size_t count);
函数参数:fd:文件描述符
buf:待写入的数据存放的缓冲区
count:指定写入的字节数
函数返回值:成功:已写的字节数
失败:-1
示例:使用read()和write()函数,先向文件中写入一些数据,之后读取出来
#include<stdio.h>
#include<stdlib.h>
#include<strings.h>
#include<unistd.h>
#include<sys/stat.h>
#include<fcntl.h>
#define MAX 128
int main(int argc,char *argv[])
{
int fdread,fdwrite;
char readbuffer[MAX]={0},writebuffer[MAX];
if(argc<2)
{
perror("arguments are too few");
exit(0);
}
//先打开文件写入数据
if((fdwrite=open(argv[1],O_WRONLY|O_CREAT|O_TRUNC,0666))<0)
{
perror("fail to open file");
exit(0);
}
printf("请输入写入的内容:");
scanf("%[^\n]",writebuffer);
write(fdwrite,writebuffer,MAX);
close(fdwrite);
//再打开文件读取刚写入的内容
int n=0,sum=0;
if((fdread=open(argv[1],O_RDONLY))<0)
{
perror("fail to open file");
exit(0);
}
while((n=read(fdread,readbuffer,MAX))>0)
{
sum += n;
printf("%s",readbuffer);
bzero(readbuffer,MAX);
}
printf("共读取到%d个字节\n",sum);
close(fdread);
return 0;
}
示例:使用文件I/O的read()/write()函数实现文件的复制
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/stat.h>
#include<fcntl.h>
#define MAX 128
int main(int argc,char *argv[])
{
int fdread,fdwrite;
char buffer[MAX]={0};
int n=0,sum=0;
if(argc<3)
{
printf("arguments are too few, Usage:%s <src_file> <dst_file>\n",argv[0]);
exit(0);
}
if((fdread=open(argv[1],O_RDONLY))<0)
{
perror("fail to open file");
exit(0);
}
if((fdwrite=open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0666))<0)
{
perror("fail to open file");
exit(0);
}
while((n=read(fdread,buffer,MAX))>0)
{
sum += n;
write(fdwrite,buffer,n);
}
printf("复制文件成功,共操作%d字节\n",sum);
close(fdread);
close(fdwrite);
return 0;
}
- 4、文件定位
函数lseek()
需要头文件:#include< unistd.h>
#include< sys/types.h>
函数原型:off_t lseek(int fd,off_t offset,int whence);
函数参数:fd:文件描述符
offset:相对于基准点whence的偏移量,正数表示向前移动,负数表示向后移动,0表示不移动
whence:基准点(取值同标准I/O内fseek()函数第三个参数)
函数返回值:成功:当前读写位置
失败:-1
其中第三个参数whence的取值如下:
SEEK_SET:代表文件起始位置,数字表示为0
SEEK_CUR:代表文件当前的读写位置,数字表示为1
SEEK_END:代表文件结束位置,数字表示为2
lseek()仅将文件的偏移量记录在内核内而不进行任何I/O操作。
注意:lseek()函数仅能操作常规文件,一些特殊的文件(例如socket文件、管道文件等)无法使用lseek()函数。
示例:读取文件的最后10个字节的数据
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/stat.h>
#include<fcntl.h>
#define MAX 10
int main(int argc,char *argv[])
{
int fd;
char buffer[MAX]={0};
int n=0,sum=0;
if(argc<2)
{
printf("arguments are too few\n",argv[0]);
exit(0);
}
if((fd=open(argv[1],O_RDONLY))<0)
{
perror("cannot open file");
exit(0);3
}
lseek(fd,-10,SEEK_END);/*文件读写位置为文件尾向前偏移10个字节*/
if(read(fd,buffer,MAX)>0)
printf("读到的数据:%s\n",buffer);
else
printf("读取出错!\n");
close(fd);
return 0;
}