前言
本文记录的是非缓存的文件IO操作,设计到的函数有:open()、write()、read(),close()这三个函数是用在用户和内核之间
一、open函数
open函数的功能就是打开一个文件。
函数形式:
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);
参数分析:
pathname --> 需要打开的文件的 路径 + 名字
flags --> 所能使用的旗标
O_CREAT 创建文件
O_RDONLY 以只读方式打开文件
O_WRONLY 以只写方式打开文件
O_RDWR 以可读写方式打开文件. 上述三种旗标是互斥的, 也就是不可同时使用, 但可与下列的旗标利用 OR(|)运算符组合.
返回值:
成功 返回新的文件描述符 (return the new file descriptor)
int --> 整型 --> 数字 --> 编号 (只能在当前进程中使用)
失败 返回 -1 错误号码会被设置
例题:当a.c文件不存在时,创建并打开文件。
代码:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{
int fd = open("./a.c", O_CREAT | O_RDWR, 0777);
if(fd < 0) {
printf("创建文件失败!!!\n");
perror("create file error");
return -1;
}
printf("create file %s success! fd = %d\n", "./a.c", fd );
close(fd);
return 0;
}
二、write函数
write函数形式:
write ( 将数据写入已打开的文件内 )
头文件:
#include <unistd.h>
定义函数:
ssize_t write (int fd, const void * buf, size_t count);
参数分析:
fd --> 需要写入的文件的文件描述符
buf --> 需要写入的数据所在的地址
count --> 需要写入的字节数
返回值:
成功 实际写入的字节数
失败 则返回-1, 错误代码存入 errno 中
例题:把hello linux!写入write.c文件中
touch.c代码:
代码如下(示例):
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{
char buf[] = "hello linux!\n";
int fd = open("./write.c", O_RDWR | O_TRUNC);
if(fd < 0) {
printf("打开文件失败!!!\n");
perror("open file error");
return -1;
}
printf("open file write.c success! fd = %d\n", fd );
int wr_ret = write(fd, buf, sizeof(buf));
printf("wr_ret = %d\n", wr_ret);
close(fd);
return 0;
}
结果显示:
三、read函数
read函数形式:
read ( 读已打开的文件内的数据 )
头文件:
#include <unistd.h>
定义函数:
ssize_t read(int fd, void *buf, size_t count);
参数分析:
fd --> 需要读取的文件的文件描述符
buf --> 需要读取的数据所在的地址
count --> 需要读取的字节数
返回值:
成功 实际写入的字节数
失败 则返回-1, 错误代码存入 errno 中
这里会设计到另外一个函数是lseek()
因为在写的时候,指针在write函数写完以后是指向数组的末尾的
所以要lseek函数把指针调整回数组的开头
lseek(移动文件的读写位置)
头文件:
#include <sys/types.h>
#include <unistd.h>
定义函数:
off_t lseek(int fd, off_t offset, int whence);
参数分析:
fd --> 需要移动文件的文件描述符
offset -->偏移量,读写操作所需要移动的距离,单位是字节的数量,可正可负(向前移或向后移)
whence :
SEEK_SET 调整当前位置为文件的开头
SEEK_CUR 就是当前位置
SEEK_END 调整当前位置为文件的结尾
返回值:
成功:文件当前的位置
发生错误时返回-1.
例题:把write.c文件中的内容读出来显示在终端
touch.c代码:
代码如下(示例):
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{
char read_buf[20];
char buf[] = "hello linux!";
int fd = open("./write.c", O_RDWR);
if(fd < 0) {
printf("打开文件失败!!!\n");
perror("open file error");
return -1;
}
printf("open file write.c success! fd = %d\n", fd );
int wr_ret = write(fd, buf, sizeof(buf));
printf("wr_ret = %d\n", wr_ret);
//调整文件的位置为开头
lseek(fd, -13, SEEK_CUR);
read(fd, read_buf, 20);
printf("读取到数据为:%s\n", read_buf);
close(fd);
return 0;
}
结果显示:
综合练习
题目:把apple.c的文件里面的内容复制到cherry.c文件中,用代码实现
代码:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char const *argv[])
{
char read_buf[20];
if(argc < 3) {
printf("输入参数必须为三个!\n");
return -1;
}
//打开文件
int fd_apple = open(argv[1], O_RDONLY); //argv[1] 输入参数:apple
int fd_cherry = open(argv[2], O_RDWR); //argv[1] 输入参数:apple
if(fd_apple < 0 && fd_cherry < 0) {
printf("打开文件失败!!!\n");
perror("open file error");
return -1;
}
printf("open file %s success! fd = %d\n", argv[1], fd_apple );
printf("open file %s success! fd = %d\n", argv[2], fd_cherry );
int rd_ret;
while(1) {
//读取apple文件里面的内容到read_buf缓冲区
rd_ret = read(fd_apple, read_buf, 128);
if(rd_ret < 128 ) {
break;
}
write(fd_cherry, read_buf, rd_ret );
memset(read_buf, 0, 128);
}
write(fd_cherry, read_buf, rd_ret ); //如果少于128,退出循环,直接写一次。如果循环过后,还有最后一次少于128字节要写,再写一次。
printf("写入成功!!!\n");
//关闭文件
close(fd_apple);
close(fd_cherry);
return 0;
}
结果显示: