文件IO相关知识
两者主要区别:
a.标准IO遵循的是ANSI C标准 ,文件IO遵循的是POSIX标准
b.标准IO利用了缓冲机制减少系统调用次数,提高效率,文件IO直接使用系统调用函数完成IO操作
c.标准IO主要进行普通文件的IO操作,文件IO适用于任意文件类型
d.标准IO使用流唯一标识一个文件,文件IO使用文件描述符来唯一标识一个文件
一、文件描述符
定义:是一个按顺序分配的最小的非负整数,当用户打开或者新建一个文件时,系统会为其分配对应的文件描述符。
三个特殊的文件描述符:
stdin – 0
stdout – 1
stderr – 2
二、相关IO操作函数
a.fopen()/fclose() – open()/close()
b.fgetc()/fputc()
c.fgets()/fputs()
d.fread()/fwrite() – read()/write()
e.ftell()/fseek()/rewind() – lseek()
1、打开文件open()
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
返回值:成功返回文件描述符,失败返回-1;
参数:
pathname:要打开文件(可以包含路径)
flags:
O_RDONLY:以只读的方式打开文件
O_WRONLY:以只写的方式打开文件
O_RDWR:以读写的方式打开文件 //前三个参数必须选择一个进行填写
O_CREAT: 如果打开文件不存在,则先创建,再打开,并且使用第三个参数为其设置权限
O_EXCL:通常和O_CREAT结合使用,判断文件是否存在
O_TRUNC:打开文件时,会将原本的内容清空
O_APPEND:打开文件时,所有的写入操作,从文件末尾开始
下面举一个例子打开文件1.txt
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int fd = open("1.txt", O_RDONLY | O_CREAT | O_EXCL, 0664);
if(fd < 0)
{
perror("open 1.txt");
return -1;
}
printf("fd = %d\n", fd);
close(fd);
return 0;
}
2、关闭文件close()
#include <unistd.h>
int close(int fd);
返回值:
成功返回0,失败返回-1;
参数:
fd:要关闭文件的文件描述符
3、读文件read()
#include <unistd.h>
*ssize_t read(int fd, void buf, size_t count);
返回值:成功实际读取到的字节数,失败返回-1,0表示读到文件末尾
参数:
fd:对应的文件描述符
buf:用户自定义的缓冲区的首地址
count:请求读取的字节数**
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int fd = open("1.txt", O_RDONLY);
if(fd < 0)
{
perror("open 1.txt");
return -1;
}
char buf[64] = {0};
int ret = read(fd, buf, 64);
if(ret < 0)
{
perror("read");
return -1;
}
printf("read %dbytes:%s\n", ret, buf);
close(fd);
return 0;
}
4.写文件write()
#include <unistd.h>
*ssize_t write(int fd, const void buf, size_t count);
返回值:成功返回成功写入的字节数,失败返回-1
参数:
fd:对应的文件描述符
buf:用户自定义的缓冲区的首地址
count:请求写入的字节数
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int fd = open("1.txt", O_WRONLY);
if(fd < 0)
{
perror("open 1.txt");
return -1;
}
char buf[64] = {0};
fgets(buf, 64, stdin);
int ret = write(fd, buf, strlen(buf));
if(ret < 0)
{
perror("write");
return -1;
}
printf("ret = %d\n", ret);
close(fd);
return 0;
}
来个小练习,使用read、write完成文件复制
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
if(argc < 3)
{
printf("User: %s src_file dst_file\n", argv[0]);
return -1;
}//这一步多看看,可以不写
int fd1 = open(argv[1], O_RDONLY);//1.txt->argv[1]
if(fd1 < 0)
{
perror("open 1.txt");
return -1;
}
int fd2 = open(argv[2], O_WRONLY | O_CREAT, 0664);//2.txt->argv[2]
if(fd2 < 0)
{
perror("open 2.txt");
return -1;
}
int ret = 0;
char buf[64] = {0};
while((ret = read(fd1, buf, 64)) > 0)
{
write(fd2, buf, ret);
}
return 0;
}
5、文件定位
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
返回值:成功返回当前文件指针的偏移量,失败返回-1;
参数:
fd:对应文件描述符
offset:偏移量,可正可负
whence:基准点
SEEK_SET:定位在文件开头
SEEK_CUR:定位在文件指针当前位置
SEEK_END:定位在文件末尾
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int fd = open("1.txt", O_RDONLY);
if(fd < 0)
{
perror("open 1.txt");
return -1;
}
int ret = lseek(fd, 0, SEEK_END);
if(ret < 0)
{
perror("lseek");
return -1;
}
printf("ret = %d\n", ret);
close(fd);
return 0;
}