Linux应用开发-文件IO操作
文件描述符
Linux中一切设备都可以当做是文件!!
通过调用系统中的I/O函数对文件进行相应的操作(open()、close()、write()、**read()**等)
当打开已经存在的文件或新创建的文件时,系统会返回一个文件描述符,他是用来指定已打开的文件。此文件描述符相当于打开这个文件的标号,是非负整数,操作这个文件描述符相当于操作这个相应的文件。
程序运行起来后(每个进程)都有一张文件描述符的表,标准输入、标准输出、标准错误输出设备文件被打开,对应的文件描述符0.1.2也会被记录
#define STDIN_FILENO 0 //标准输入的文件描述符
#define STDOUT_FILENO 1 //标准输出的文件描述符
#define STDERR_FILENO 2 //标准错误的文件描述符
当程序运行起来后打开其他文件时,系统会返回文件描述符表中最小可用的文件描述符,并把这个文件描述符记录在表中。Linux中一个进程最多智能打开1024个文件,所以当文件不再使用时要及时调用close()关闭文件
常用I/O函数
必要的头文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int open(const char *pathname, int flags, mode_t mode)
- 功能
- 打开文件,如果文件不存在则创建
- 参数
- pathname: 文件的路径及文件名。
- flags: 打开文件的行为标志,如,以只读方式(O_RDONLY,第一个为字母不是数据)打开,以读写或新建新文件的方式(O_RDWR|O_CREAT)打开。
- mode: 这个参数,只有在文件不存在时有效,指新建文件时指定文件的权限
- 返回值
- 成功:成功返回打开的文件描述符
- 失败:-1
int close(int fd)
-
功能
- 关闭已打开的文件
-
参数
- fd: 文件描述符,open()的返回值
-
返回值
- 成功:0
- 失败:-1
ssize_t write(int fd, const void *addr, size_t count)
- 功能
- 把指定数目的数据写到文件(fd)
- 参数
- fd: 文件描述符
- addr: 数据首地址
- count: 写入数据的长度(字节),一般情况下,数据有多少,就往文件里写多少,不能多也不能少
- 返回值
- 成功:实际写入数据的字节个数
- 失败:-1
ssize_t read(int fd, void *addr, size_t count)
- 功能
- 把指定数目的数据读到内存(缓冲区)
- 参数
- fd: 文件描述符
- addr: 内存首地址
- count: 读取的字节个数
- 返回值
- 成功:实际读取到的字节个数
- 失败:-1
案例
Linux cp 命令简单实现
/* ./cp src.c des.c */
#include "stdio.h"
#include "unistd.h"
#include "fcntl.h"
#include "string.h"
int main(int argc, char *argv[])
{
int src_fd, des_fd;
char read_buff[128] = {0};
int src_ret = 0;
if (argc < 3)
{
printf("please input src & des file\n");
return -1;
}
src_fd = open(argv[1], O_RDONLY);
if (src_fd < 0)
{
printf("open src file \n");
return -1;
}
printf("open src file ok id:%d\n", src_fd);
des_fd = open(argv[2], O_CREAT | O_WRONLY, 0777);// 创建传参进来的文件名 并权限为777
if (des_fd < 0)
{
printf("open des file \n");
return -1;
}
printf("open des file ok id:%d\n", des_fd);
while (1)
{
src_ret = read(src_fd, read_buff, 128);
if (src_ret < 128)
break;
write(des_fd, read_buff, src_ret);
memset(read_buff, 0, 128);
}
write(des_fd, read_buff, src_ret);
close(src_fd);
close(des_fd);
return 0;
}
运行代码前先创建一个src.c文件并写入525byte
./cp src.c des.c
可以看到des.c字节数和src.c字节数相同
我们可以看到我们创建的权限为777 但结果只有775
这是因为Linux中有个叫 umask 默认权限的值
umask
文件I/O
大多数Linux文件I/O只需要5个函数 open read write close lseek
现在说下lseek
- 每个打开文件都有一个与其相关联的“当前文件位移量”。它是一个非负整数,用以度量从文件开始处计算的字节数。就是改变文件描述符的偏移位置。
off_t lseek(int fildes, off_t offset, int whence)
- whence:
SEEK_SET : 把偏移量设为offset, 从文件头开始.
SEEK_CUR : 把当前偏移量加上offset的值
SEEK_END : 先从文件尾开始偏移offset的值 - 返回值:成功返回定位之后的文件指针偏移 失败返回 -1
案例
#include "stdio.h"
#include "unistd.h"
#include "fcntl.h"
int main(int argc, char *argv[])
{
int fd;
char write_buf[] = "hello linux";
char read_buf[128] = {0};
fd = open("./a.c", O_RDWR | O_TRUNC);
if (fd < 0)
{
printf("open file a.c ail\n");
return -1;
}
printf("open file a.c success fd:%d\n", fd);
write(fd, write_buf, sizeof(write_buf));
lseek(fd, 0, SEEK_SET);//把偏移量设为offset, 从文件头开始 偏移0个int单位
read(fd, read_buf, 128);
printf("read_buff = %s\n", read_buf);
close(fd);
return 0;
}