文件I/O操作
终端输入“ls -l”查看当前目录下所有文件的信息:
drwxr-xr-x. 2 anxier anxier 4096 1月 15 00:29 desktop
drwxr-xr-x. 4 anxier anxier 4096 1月 3 13:31 document
drwxrwxr-x. 6 anxier anxier 4096 1月 11 00:00 workspace
第一栏的信息包含10字符。第1个字符,表示文件的类型;第2~4位,代表文件所有者(User)的权限,分别为读、写、执行;第5~7位,代表文件所有者的同组用户(Group)的权限,分别是读、写、执行;第8~10位,代表其他用户(Other)的权限,分别为读、写、执行。
位 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| | r | w | x | r | w | x | r | w | x |
第1位为Linux文件类型符号:
符号 | 文件类型 | 符号 | 文件类型 |
- | 普通文件 | d | 目录文件 |
l | 链接文件 | b | 块设备文件 |
c | 字符设备文件 | p | 管道文件 |
s | 套接口文件 | | |
1、普通文件
分为文本文件和二进制文件。是计算机用户和操作系统用于存放数据、程序等信息的文件。
2、目录文件
是文件系统中一个目录所包含的目录项组成的文件,只允许系统进行修改,用户进程可以读取目录文件,但不能进行修改。
3、设备文件
用于操作系统与I/O设备提供连接的一种文件,分为字符设备文件和块设备文件。
4、链接文件
又称为符号链接文件,它提供了共享文件的一种方法,在链接文件中不是通过文件名实现文件共享,而是通过链接文件所包含的指向文件的指针来实现对文件的访问。链接文件可以在不同文件系统之间建立一种链接关系。
5、管道文件
主要用于在进程间传递数据,是Linux进程间的一种通信机制。
6、套接口文件
主要用于在不同计算机的进程间的通信,也称为套接字。
分为3种:流式套接口、数据报套接口和原始套接口。流式套接口就是TCP套接口(面向连接的套接口),数据报套接口就是UDP套接口(无连接的套接口),原始套接口用“SOCK_RAW”表示。
文件重定向
1、重定向标准输出
command > filename #把标准输出重定向到filename文件中
command >> filename #把标准输出重定向到filename文件中,方式是追加在现有内容的后面
command 1> filename #把标准输出重定向到一个文件中
> myfile #创建一个长度为0的空文件
2、重定向标准输入
command < filename #以filename文件的内容作为command命令的标准输入
command < file1 > file2 #以file1文件的内容作为command命令的标准输入,并以file2文件作为命 #令执行结果的标准输出
command << delimiter #从标准输入中读入,直至遇到delimiter分界符
3、重定向标准出错
command 2> filename #把标准出错信息重定向到filename文件中
command 2>> filename #把标准出错信息重定向到一个文件中(追加)
command 1> file1 2> file2 #将标准输出重定向到file1中,然后再把标准出错重定向到file2
command > filename 2> &1 #把标准输出和标准出错一起重定向到filename文件中
command >> filename 2> &1 #把标准输出和标准出错一起重定向到filename文件中(追加)
command > filename 2> &1 << delimiter #把标准输出和标准出错一起重定向到filename文件中,直 #至遇到delimiter分界符
文件的创建、打开和关闭
1、open函数
#include
#include
#include
int open(const char *pathname,int flags); //打开一个现有的文件
int open(const char *pathname,int flags,mode t_mode); //打开文件不存在,则先创建
参数flags用于描述文件打开方式的,常数定义在头文件中。
flags的取值及其含义:
flags的值 | 含义 |
O_RDONLY | 以只读方式打开文件 |
O_WRONLY | 以只写方式打开文件 |
O_RDWR | 以读写方式打开文件 |
O_CREAT | 若所打开文件不存在则创建此文件。使用此选择项时,需同时使用第三个参数mode说明该新文件的存取许可权位 |
O_EXCL | 如果同时指定了O_CREAT,而文件已经存在,则导致调用出错 |
O_TRUNC | 如果文件存在,而且为只读或只写方式打开,则将其长度截断为0 |
O_NOCTTY | 如果pathname指的是终端设备(tty),则不将此设备分配作为此进程的控制终端 |
O_APPEND | 每次写时都加到文件的尾端 |
O_NONBLOCK | 如果pathname指的是一个FIFO、一个块特殊文件或一个字符特殊文件,则此选择项为此文件的本次打开操作和后续的I/O操作设置为非阻塞方式 |
O_NONELAY | O_NONBLOCK |
O_SYNC | 只在数据被写入外存或者其他设备之后操作才返回 |
参数mode的取值及其含义:
mode取值 | 对应八进制数 | 含义 |
S_ISUID | 04000 | 设置用户识别号 |
S_ISGID | 02000 | 设置组识别号 |
S_SVTX | 01000 | 粘帖位 |
S_IRUSR | 00400 | 文件所有者的读权限位 |
S_IWUSR | 00200 | 文件所有者的写权限位 |
S_IXUSR | 00100 | 文件所有者的执行权限位 |
S_IRGRP | 00040 | 所有者同组用户的读权限位 |
S_IWGRP | 00020 | 所有者同组用户的写权限位 |
S_IXGRP | 00010 | 所有者同组用户的执行权限位 |
S_IROTH | 00004 | 其他用户的读权限位 |
S_IWOTH | 00002 | 其他用户的写权限位 |
S_IXOTH | 00001 | 其他用户的读执行权限位 |
头文件中定义了3个常用的逻辑组合:
-
S_IRWXU=S_IRUSR | S_IWUSR | S_IXUSR 文件所有的读写执行权限
-
S_IRWXG=S_IRGRP | S_IWGRP | S_IXGRP文件所有者同组用户的读写执行权限
-
S_IRWXO=S_IROTH | S_IWOTH | S_IXOTH其他用户组的读写执行权限
2、creat函数
#include
#include
#include
int creat(const char *pathname,mode_t mode);
返回:若成功,返回以只写方式打开的文件描述符,若出错为-1;
creat函数等效于:
open(pathname,O_WRONLY | O_CREAT | O_TRUNC, mode);
3、close函数
#include
int close(int fd);
返回:若成功返回0,若出错返回-1。参数fd是需关闭文件的文件描述符。
当一个进程终止时,它所有的打开文件都由内核自动关闭。
文件的定位
#include
#include
off_t lseek(int fd,off_t offset,int whence);
返回:若成功,返回新的文件位移量,若出错为-1。
whence | 含义 |
SEEK_SET | 将该文件的位移量设置为距文件开始处offset个字符 |
SEEK_CUR | 将该文件的位移量设置为当前值加offset个字符,offset可为正或负 |
SEEK_END | 将该文件的位移量设置为文件长度加offset个字符,offset可为正或负 |
确定一个打开文件的当前位移量:
off_t currpos; //定义变量currpos的数据类型为off_t
currpos=lseek(fd,0,SEEK_CUR); //offset值为0
文件的读写
1、read函数
#include
ssize_t read(int fd,void *buf,size_t count);
返回:读到的字节数,若已到文件尾部返回0,若出错为-1。其中参数fd表示要进行读操作的文件的描述符,buf是一个指向缓冲区的指针,该缓冲区存放将要读取到终端的数据,count表示本次操作将要读取的数据的字节数。
2、write函数
#include
ssize_t write(in fd,void *buf,size_t count);
返回:若成功为已写的字节数,若出错为-1。其中fd表示进行写操作的文件的描述符,buf是一个指向缓冲区的指针,该缓冲区将要写入文件的数据,count表示本次操作将要写入文件的数据的字节数。
函数返回值通常与参数count的值相同,否则表示出错。
文件的属性操作
1、改变文件访问权限
#include》
#include
int chmod(const char *pathname,mode_t mode);
int fchmod(int fd,mode_t mode);
返回:若成功则为0,若出错则为-1。
2、改变文件的所有者
#include
#include
int chown(const char *pathname,uid_t owner,gid_t group);
int fchown(int fd,uid_t owner,gid_t group);
in lchown(const char *pathname,uid_t owner,gid_t group);
返回:若成功为0,否则出错为-1。
-
chown:修改指定文件的所有者。
-
fchown:修改已打开文件的所有者。
-
lchown:针对符号链接文件。
3、重命名
#include
int rename(const char *oldname,const char *newname);
返回:若成功为0,若出错则为-1。rename调用是否成功,将与oldname指向普通文件还是目录文件:
oldname指向 | newname所示文件不存在 | newname所示文件村存在 | |
newname指向普通文件 | newname指向目录文件 | ||
普通文件 | 文件成功被重命名 | newname别删除,原名为oldname的文件被重命名为newname | 错误 |
目录文件 | 文件成功被重命名 | 错误 | 若该目录文件为空目录则被删除,oldname被重命名;否则出错。 |
【newnme不能包含有oldname的路径前缀,也就时说,不能将一个目录文件重命名为它的子文件。】
4、修改文件长度
#include
#include
int truncate(const char *pathname,off_t len);
int ftruncate(int fd,off_t len);
返回:若成功则为0,若出错则为-1。
文件的其他操作
1、stat函数返回文件的信息
#include
#include
int stat(cosnt char *pathname,struct stat *sbuf);
int fstat(int fd,struct stat *sbuf);
int lstat(const char *pathname,struct stat *sbuf);
返回:若成功则为0,出错为-1。
当文件为符号链接时,lstat返回符号链接的信息,而不是有该符号链接引用的文件的信息。
UNIX/LINUX常见基本系统数据类型 | |
类型 | 说明 |
caddr_t | 内存地址 |
clock_t | 时钟滴答计数器(进程时间) |
comp_t | 压缩的时钟滴答 |
dev_t | 设备号(主和次) |
fd_set | 文件描述符) |
fpos_t | 文件位置 |
gid_t | 数值组ID |
ino_t | i节点编号 |
mode_t | 文件类型,文件创建方式 |
nlink_t | 目录项的连接计数 |
off_t | 文件长度和位移量(带符号的) |
pid_t | 进程ID和进程组ID(带符号的) |
ptrdiff_t | 两个指针相减的结果(带符号的) |
rlim_t | 资源限制 |
sig_atomic_t | 能原子地存取的数据类型 |
sigset_t | 信号集 |
size_t | 对象(例如字符串)长度(不带符号的) |
ssize_t | 返回字节计数的函数(带符号的)(如read,write) |
time_t | 日历时间的秒计数器 |
uid_t | 数值用户ID |
wchar_t | 能表示所有不同的字符码 |
2、dup和dup2函数复制一个现存的文件描述符
#include
int dup(int fd);
int dup2(int fd,int fd2);
返回:若成功为新的文件描述符,出错为-1。
3、fcntl函数改变已经打开文件的性质
#include
#include
#include
int fcntl(int fd,int cmd);
int fcntl(int fd,int cmd,long arg);
返回:若成功则依赖于cmd,出错为-1。
参数cmd表示此调用所要执行的操作。参数arg是可选的。
cmd取值及相应操作 | |
cmd取值 | 相应操作 |
F_DUPFD | 复制一个现存的文件描述符 |
F_GETFD | 获得文件描述符标记 |
F_SETFD | 设置文件描述符标记 |
F_GETFL | 获得文件状态标记 |
F_SETFL | 设置文件状态标记 |
F_GETOWN | 获得异步I/O权 |
F_SETOWN | 设置异步I/O权 |
F_GETLK | 获得记录锁 |
F_SETLK | 设置记录锁 |
F_SETLKW | 设置记录锁,必要时等待 |
4、sync函数和fsync函数
#include
void sync(void);
int fsync(int fd);
返回:若成功为0,出错为-1。
特殊文件的操作
1),mkdir创建目录
#include
#include
int mkdir(const char *pathname,mode_t mode);
返回:成功为0,出错为-1。
2),rmdir函数删除空目录
#include
int rmdir(const char *pathname);
返回:成功为0,出错为-1。
3),opendir函数打开目录
#include
#include
DIR *opendir(const char *pathname);
返回:成功为指针,出错为NULL。
4),closedir函数关闭目录
#include
#include
int closedir(DIR *dp);
返回:成功为0,出错为-1。dp是DIR类型的指针,指向要关闭的目录文件。
5),readdir函数读取目录文件
#include
#include
struct dirent *readdir(DIR *dp);
返回:成功为指针,出错或在目录尾为NULL。
6),chdir、fchdir和getcwd函数
进程用chdir和fchdir函数可以更改当前工作的目录。
#include
int chdir(const char *pathname);
int fchdir(int fd);
返回:成功为0,出错为-1。
函数getcwd得到当前工作目录的绝对路径名。
#include
char *getcwd(char *buf,size_t size);
返回:成功返回buf,出错为NULL。
链接文件的操作
1、硬链接
1)创建链接
#include
int link(const char *pathname1,const char *pathname2);
返回:成功为0,出错为-1。创建一个新目录项pathname2,它引用pathname1。
2)删除链接
#include
int unlink(const char *pathname);
返回:成功为0,出错为-1。必须对包含该目录项的目录具有写和执行许可权:
-
拥有该文件
-
拥有该目录
-
具有超级用户优先级
用remove函数解除对一个文件或目录的连接:
#include
int remove(const char *pathname);
返回:成功为0,出错为-1。
2、符号链接
symlink函数用于创建一个符号链接:
#include
int symlink(const char *actualpath,const char *sympath);
返回:成功为0,出错为-1。
readlink函数用于打开一个链接并获取该链接的名字:
#Include<<font color="#000000">unistd.h>
int readlink(const char *pathname,char *buf,int bufsize);
返回:若成功则返回读取的字节数,出错为-1。
管道文件的操作
pipe函数创建管道
#includeio.h>
int pipe(int filedes[2]);
返回:成功为0,出错为-1。filedes返回两个文件描述符,分别是管道的两端。