Linux 文件IO中的系统IO
Linux 下一切皆文件
— 鲁迅
Linux 下的文件类型:
1,普通文件(regular):存在于外部存储器中,用于存储普通数据。
2,目录文件(directory):用于存放目录项,是文件系统管理的重要文件类型。
3,管道文件(pipe):一种用于进程间通信的特殊文件,也称为命名管道 FIFO。
4,套接字文件(socket):一种用于网络间通信的特殊文件。
5,链接文件(link):用于间接访问另外一个目标文件,相当于Windows 快捷方式。
6,字符设备文件(character):字符设备在应用层的访问接口。
7,块设备文件(block):块设备在应用层的访问接口。
————————————————————————–
--------------------------系统IO-------------------
由系统直接提供的函数接口,特点就是特别简介,功能单一
没有设置缓冲区,因此对于海量数据效率较低
套接字文件以及设备文件只能使用系统IO 来访问
一、打开文件
(一)man 手册如何查询:
1、man 2 open
2、系统IO 函数接口open使用: 打开文件
定义函数
int open(const char * pathname, int flags);(用于文件存在的情况)
int open(const char * pathname, int flags, mode_t mode); (用于不知道文件在不在的情况)
参数分析
pathname:需要打开的文件名字 路径+文件名(如果没有写路径,就默认为当前路径)
flags :标志(标志实质是就是一个数字)
O_RDONLY-----以只读方式打开文件
O_WRONLY-----以只写方式打开文件
O_RDWR-----以可读写方式打开文件
上述三种旗标是互斥的, 也就是不可同时使用。但可与下列的标志利用 OR(|)运算符组合
O_CREAT-----若欲打开的文件不存在则自动建立该文件(如果指定的文件已经存在,不会重新生成一个新的文件并覆盖旧文件)
O_EXCL-----文件存在会返回错误-1,如果 O_CREAT 也被设置, 此指令会去检查文件是否存在. 文件若不存在则建立该文件。若是存在,则返回值为-1;
O_TRUNC-----擦除文件内容再打开(原来文件的类容会被擦除)
O_APPEND-----当读写文件时会从文件尾开始移动,追加方式打开(不会清除文件内容)
mode :创建文件的权限 一般情况下系统默认设置为 0002
返回值:
成功 返回一个新的文件描述符fd(int类型)
失败 返回 -1
3、 操作练习:
如果文件不存在如何在程序中自行创建
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
int main(void)
{
int fd;
fd = open("3.c", O_RDONLY | O_CREAT | O_EXCL, 0666);
if (fd < 0)
{
printf("文件已经存在\n");
return -1;
}
else
{
printf("文件创建成功\n");
close(fd);
return 0;
}
}
二、写入文件,读文件
1、系统IO 函数接口write使用: 写入文件
头文件:#include <unistd.h>
定义函数:
ssize_t write (int fd, const void * buf, size_t count);
参数分析:
fd --> 需要写入的文件的描述符
buf --> 需要写入的数据所在的内存地址
count --> 需要写入的字节数
返回值:
返回实际写入文件的字节数
当有错误发生的时候会返回-1
2、系统IO 函数接口read使用: 读文件
头文件:#include <unistd.h>
定义函数:
ssize_t read(int fd, void * buf, size_t count);
参数分析:
fd --> 需要写入的文件的描述符
buf --> 读取到的数据存放的位置(用户的缓冲区)
count --> 需要写入的字节数
返回值:
返回实际读到的字节数(如果返回值比count小,可能读到了文件的末尾)
当有错误发生的时候会返回-1
3、 关闭文件:
头文件:#include <unistd.h>
定义函数:
int close(int fd);
参数分析:
fd --> 需要关闭的文件的描述符
4、 操作练习:
打开一个文件,对文件写入数据并且读取出来。
#include "stdio.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
int main(void)
{
int fd;
char buf[] = "abcdefgh";
fd = open("1.c", O_RDWR);
if(fd < 0)
{
printf("打开文件失败\n");
return -1;
}
printf("打开文件成功\n");
write(fd, buf, sizeof(buf));
//重新打开该文件(否则读不到数据),因为现在的文件指针指向的是文件末尾
close(fd);
memset(buf, 0, sizeof(buf));
fd = open("1.c", O_RDWR);
if(fd < 0)
{
printf("打开文件失败\n");
return -1;
}
printf("打开文件成功\n");
read(fd, buf, sizeof(buf));
printf("写入的数据是:%s", buf);
close(fd);
return 0;
}
三、移动文件的读写位置
头文件:#include <unistd.h>
定义函数:
off_t lseek(int fildes, off_t offset, int whence);
参数分析:
fildes --> 需要移动读写位置的文件的描述符
offset --> 偏移量设置(偏移到文件的哪个位置)
whence --> 偏移的模式:
SEEK_SET 参数 offset 即为新的读写位置
SEEK_CUR 以目前的读写位置往后增加 offset 个位移量
SEEK_END 将读写位置指向文件尾后再增加 offset 个位移量
当 whence 值为 SEEK_CUR 或SEEK_END 时, 参数 offet 允许负值的出现(使用负数作
为偏移量,向文件当前位置或文件末尾的相反方向移动。)
返回值:
成功时返回当前的位置,也就是距离文件开头的字节数
当有错误发生的时候会返回-1
四、练习:
尝试实现类似 cp 命令的操作
#include "stdio.h"
#include "unistd.h"
#include <fcntl.h>
#include <string.h>
int main()
{
int rd_fd, wd_fd;
char buf[256];
int rd_ret = 0;
rd_fd = open("1.c", O_RDONLY, 0666);
if(rd_fd < 0)
{
printf("打开文件1失败");
return -1;
}
printf("打开文件1成功\n");
wd_fd = open("2.c", O_RDWR, 0666);
if(wd_fd < 0)
{
printf("打开文件2失败");
return -1;
}
printf("打开文件2成功\n");
while(1)
{
rd_ret = read(rd_fd, buf, 128);//rd_ret得到每次读到的字节数
printf("%d", rd_ret);
if(rd_ret < 128)//表示数据读完了
{
break;
}
write(wd_fd, buf, rd_ret);//写入文件
}
write(wd_fd, buf, rd_ret);//最后一次读到的数据 写入文件
memset(buf, 0, 128);//清空buf数组
close(rd_fd);
close(wd_fd);
return 0;
}