学习目标:
核心思想:一切皆文件
学习内容:
文件IO --- 系统调用
文件IO --- 系统调用
1.概念
文件描述符 --- 系统调用这组函数中,对打开文件的 标识
整型数值
0~1023 //1024个
0 -- stdin
1 -- stdout
2 -- stderr
2.基本操作
a.打开 --- open
b.读写 --- read / write
c.关闭 --- close
文件io:
操作系统为了方便用户使用系统功能而对外提供的一组系统函数。
称之为 系统调用
其中有个 文件IO
一般都是对设备文件操作,当然也可以对普通文件进行操作。
一个基于Linux内核的没有缓存的IO机制
------------------------------------------------------------------
文件操作:
缓存 操作对象 具体操作
标准IO 全缓存/行缓存 文件指针(流指针)FILE * 1.打开 --fopen
2.读写
fgetc/fputc
fgets/fputs
fread/fwrite
3.关闭
fclose
4.定位
fseek/ftell/rewind
文件IO 不带缓存 文件描述符 (整数) 1.打开 --open
2.读写 --read/write
3.关闭 --close
4.定位 --lseek
FILE *fp <--操作系统内核([fileno])--->[1.txt]
//文件IO
文件描述符 <----------操作系统--------->[1.txt] //硬盘
stdin --- 0
stdout --- 1
stderr --- 2
----------------------------------------------------------------
特性:
.1 没有缓存区 (//可以认为数据直接交给了内核 )
.2 操作对象不在是流(FILE *),而是文件描述符(整数)
.3文件描述符
很小的非负的整数 int 0-1023
内核每打开一个文件就会获得一个文件 描述符
每个程序在启动的时候操作系统默认为其打开
三个描述符与流对象匹配:
0 ==>STDIN_FILENO === stdin
1 ==>STDOUT_FILENO == stdout
2 ==>STDERR_FILENO == stderr
stdin,stdout,stderr,===>FILE*
库函数:
优点:
a.方便,功能多
b.可移植性好
标准
不足:
c.可能存在 安全性 隐患
系统调用:
优点:
a.使用起来,简单 ,功能简单
b.安全性高
c.设备文件 ---- 文件IO
缺点:
c.很多复杂功能需要自己封装设计
d.可移植性差
标准IO库: 系统调用
fopen open
r O_RDONLY
w O_WRONLY|O_CREAT|O_TRUNC
r+ O_RDWR
w+ O_RDWR |O_CREAT|O_TRUNC
a O_WRONLY|O_CREAT|O_APPEND
a+ O_RDWR |O_CREAT|O_APPEND
O_APPEND
ansi c
unistd.h ===>POSIX 标准库
fopen fgetc/s/fread system-v 标准
rw- rw- r--
110 100
6 6 4
fopen open
w O_WRONLY|O_CREAT|O_TRUNC
w+ O_RDWR|O_CREAT|O_TRUNC
r O_RDONLY
r+ O_RDWR
a O_WRONLY|O_CREAT|O_APPEND
a+ O_RDWR|O_CREAT|O_APPEND
open
read /write
close
lseek
库函数 本质上是 对系统调用 的封装
fopen open
r O_RDONLY
r+ O_RDWR
w //文件存在
//文件不存在 fopen(,"w"); ---> open(,O_WRONLY|O_CREAT|O_TRUNC);
//O_WRONLY|O_CREAT|O_TRUNC
w+
//O_RDWR|O_CREAT|O_TRUNC
a //O_WRONLY|O_APPEND
a+ //O_RDWR|O_APPEND
a // O_WRONLY|O_APPEND ==> flags
2.函数接口
1.open
int open(const char *pathname, int flags);
open("1.c",O_WRONLY|O_CREAT,0666 );
int open(const char *pathname, int flags,int mode);
功能:
获得一个文件描述符
参数:
pathname:文件名
flags:
必须项:他们之间是互斥的,所以有且只能有一个
O_RDONLY
O_WRONLY
O_RDWR
可选项:
O_CREAT, 创建文件 //这个标志量存在,则需要指定参数 mode
O_EXCL, 需要和O_CREAT同时使用,表示新建的文件不存在,成功,否则open就会失败
O_TRUNC 文件内容清空
O_APPEND追加
O_RDONLY
O_WRONLY|O_APPEND
fopen()
r ---- O_RDONLY
r+ O_RDWR
w O_WRONLY|O_TRUNC|O_CREAT ,0666
w+ O_RDWR|O_TRUNC|O_CREAT ,0666
a O_WRONLY|O_APPEND|O_CREAT ,0666
a+ O_RDWR|O_APPEND|O_CREAT ,0666
fopen open
r O_RDONLY
r+ O_RDWR
w O_WRONLY| O_CREAT|O_TRUNC,0666
w+ O_RDWR| O_CREAT|O_TRUNC,0666
a O_WRONLY|O_APPEND|O_CREAT,0666
a+ O_RDWR|O_APPEND|O_CREAT,0666
//后面
O_NOCTTY,不是终端设备
O_ASYNC 异步io,什么时候io不确定,
O_NONBLOCK 非阻塞
最终文件的权限
~umask & 0666
返回值:
成功返回文件描述符 (最近最小未使用)
失败返回-1
touch --- 如果文件不存在,则创建该文件(空文件)
如果文件存在,则更新文件的时间戳(makefile)
2.write
char buf[1024];
ssize_t write(int fd, const void *buf, size_t count);
功能:
通过文件描述符向文件中写一串数据
参数:
fd :文件描述符
buf:要写入文件的字符串的首地址
count:要写入字符的个数
返回值:
成功返回 实际写入的个数
失败返回 -1 & errno 被设置
3.read
ssize_t read(int fd, void *buf, size_t count);
功能:
通过文件描述符读取文件中的数据
参数:
fd :文件描述符
buf : 存放数据空间的首地址
count:要读到数据的字节个数
返回值:
成功返回读到数据的个数
失败返回-1
读到文件结尾返回0
注意:
read读出来的数据,不是字符串,
如果要输出字符串,需要单独进行处理。
基本操作
打开 - open
读写 - read/write
关闭 - close
思路:
1.打开
fd_s --src
fd_d --dest
2.读写
3.关闭
close
使用read,write复制文件。
fseek ftell
4.lseek //fseek, rewind ftell
off_t lseek(int fd, off_t offset, int whence);
功能:
定位文件的位置
参数:
fd :文件描述符
offset:偏移量
正:向后偏移
负:向前偏移
零:不偏移
whence:
SEEK_SET
SEEK_CUR
SEEK_END
正 空洞
返回值:
成功返回 偏移量
失败返回 -1
lseek(fd,0,SEEK_END);
练习:
创建空洞文件
a.先偏移 --lseek
b.写一下 --write
off_t len =lseek(fd,0,SEEK_END); //获取到文件的大小
//空洞文件
1.定位
lseek(fd,len,SEEK_SET);
2.写
write(fd,"",1);
空洞文件:
1.偏移
2.写操作 面试题:
文件IO的文件描述符最大值是多少? ==>1024 个,范围0-1023 《==ulimit -a 【总结】
文件IO:
1.open
2.read/write
3.close
4.lseek
--------------------------------------------------------------------
fileno FILE* fp -> int fd
int fileno(FILE *stream);
功能:
获得一个文件流指针中的文件描述符
参数:
stream:文件流指针
返回值:
成功返回文件描述符
失败返回-1
2.fdopen int fd -> FILE *fp
FILE *fdopen(int fd, const char *mode);
功能:
将文件描述符转化为文件流指针
参数:
fd:已经打开的文件描述符
mode:
"r"
"r+"
"w"
"w+"
"a"
"a+"
返回值:
成功返回文件流指针
失败返回NULL
文件IO与标准IO的比较:
文件IO 用于底层设备相关的开发,但是
效率和安全性以及移植性没有标准IO方便。
如果是纯上层开发,优先选择使用标准IO 。
-----------------------------------------------------------------
目录也是文件:
类似标准IO
目录文件 ----> 目录流指针 ----> 提供给相关函数操作
目录文件 -----> 流 (目录流指针)
01-打开目录 -- opendir
02-读目录 -- readdir
03-关闭目录 -- closedir
mkdir tmp
cd tmp
touch file.txt
文件属性,目录 inode,name ls 123
1.打开目标目录
2.读取目录
3.关闭目录
目录 当文件看,只不过操作函数和操作文件函数不一样。
1.opendir
DIR * opendir(const char *name); //cd /home/linux/tmp
功能:
打开一个目录获得一个目录流指针
参数:
name:目录名
返回值:
成功 返回目录流指针
失败 返回NULL
2.readdir
struct dirent *readdir(DIR *dirp);
功能:
从目录流中读取文件信息并将保存信息的结构体
地址返回
参数:
dirp:目录流指针
返回值:
成功 包含文件信息的结构体指针
出错或者读到目录流末尾返回 NULL3、关闭目录
int closedir(DIR *dirp);
功能:关闭之前已经打开的目录流对象
参数:
opendir的返回结果中目录流对象
返回值:
成功 0
失败 -1;
目录:
cd
mkdir
rmdir
3.chdir
chdir ("/home/linux"); "../../"
fopen("1.mp4")
int chdir(const char *path);// /home/linux
功能:
改变当前程序的工作路径
参数:
path:改变到的路径
返回值:
成功返回0
失败返回-1
/home/linux/Desktop/Music
"file.txt"
chdir("/root");
"file.txt"
4.getcwd //pwd
char *getcwd(char *buf, size_t size);
功能:
获得当前的工作路径
参数:
buf:保存工作路径空间的首地址
size:保存路径空间的长度
返回值:
成功返回包含路径空间的字符串首地址
失败返回NULL
5.mkdir
int a =200;
int mkdir(const char *pathname, mode_t mode);//777 666 --x--x--x
功能:
创建一个目录
666-
参数:
pathname:路径
mode:
mode & ~umask 0002
返回值:
成功返回0
失败返回-1
6.rmdir rm -fr rmdir
int rmdir(const char *pathname);
功能:
删除一个空目录文件
参数:
pathname:目录文件的名字
返回值:
成功返回0
失败返回-1
//目录操作:
1.opendir
2.readdir
3.closedir
--------
4.chdir
5.getcwd
6.mkdir
7.rmdir
文件名:
opendir
readdir
printf("%s",p->name);
close(dir)
drwxrwxr-x 2 linux linux 4096 Mar 22 19:31 ./
说明:
d rwx rwx r-x 2 linux linux 4096 Mar 22 19:31 ./
文件类型 相关权限 目录 所有者 所在组 文件大小 最后被修改的
---------------------------
硬链接:
同一个文件,多个名字。
软链接:
某一个文件的快捷方式。
---------------------------
ls ll
文件属性的获取
struct stat st;
struct stat*st;
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *path, struct stat *buf);
//软链接 --- lstat 获取软链接这个链接文件本身的属性信息,而不是连接到的目标文件的属性信息。
【linux下时间的获取】:
1.获取秒数 --time() 秒数
2.转换为需要个格式 ()
系统时间的获取:
1.time
time_t time(time_t *t);
time_t tm;
time(&tm)
tm = time(NULL);
功能:
获得1970年到现在的秒数
参数:
t:存放秒数的空间首地址
返回值:
成功返回1970年到现在的秒数
失败返回-1
2.localtime
struct tm *localtime(const time_t *timep);
功能:
将一个秒数转化成日历时间
参数:
timep:保存秒数空间的地址
返回值:
成功返回保存日历时间结构体的指针
失败返回NULL
3.ctime
char *ctime(const time_t *timep);//date
功能:
将时间秒数转化成字符串
参数:
timep:保存时间空间的地址
返回值:
成功返回获得时间字符串的首地址
失败返回NULL
总结:
获取文件属性信息
stat
fstat
lstat --- 软链接文件本身信息
1. 文件的类型 和 权限 ---- st_mode
2. 文件的硬链接数 ---- st_nlink
3. 文件所有者 ---- st_uid + getpwuid
4. 文件所属组 ---- st_gid + getgrgid
5. 文件大小信息 ---- st_size
6. 文件的最后修改的时间---- st_ctime + localtime()/ctime()
7. 文件的名字
【思考问题】:
目录操作:
1.opendir -->DIR * 目录流指针
2.readdir()
3.closedir()
-------------------------
4.chdir //cd
5.getcwd //pwd
6.mkdir //mkdir
7.rmdir
-------------------------
回顾】:
1.目录文件
opendir
readdir
closedir
2.其它目录操作
chdir
getcwd
mkdir
rmdir //删除的目录必须为空
学习产出:
使用read,write复制文件