第六章.文件操作
知识点总结:
一.目录树.根目录下的枝目录
/bin:用于存放普通用户可执行的命令,如ls,cp,mkdir;
/boot:Linux的内核及启动系统时所需要的文件,为保证激动文件更加安全可靠,通常把该目录放在独立的分区上;
/dev:设备文件的存储目录,如硬盘,光盘;
/etc:存放系统的配置文件,如账号密码;
/home:普通用户的主目录
/lib:存放各种库文件;
/proc:该目录是一个虚拟文件系统,只有系统运行时才存在;
/root:超级用户root的主目录;
/sbin:存放用于管理系统的命令;
/tmp:临时文件目录;
/usr:存放应用程序及相关文件;
/var:用于存放系统中经常变换的文件,如日志文件,用户邮件.
二.文件分类
普通文件(regular file)
目录文件(directory file)
字符特殊文件(character special file):用于表示系统中字符类型的设备,如键盘鼠标;
块特殊文件(block special file):表示系统中块类型的设备,如硬盘,光驱,访问这些数据以块的方式进行;
FIFO:命名管道,用于进程间通信;
套接字(socket):主要用于网络通信,也可用于一台主机上进程间的通信;
符号连接(symbolic link):指向另一个文件,是另一个文件的引用.
三.文件的访问权限
r:可读
w:可写
x:可执行
修改文件权限的系统命令:chmod <权限值> <文件名>
字符常量:
用户:S_IRUSR S_IWUSR S_IXUSR
所属组:S_IRGRP S_IWGRP S_IXGRP
其他人:S_IROTH S_IWOTH S_IXOTH
四.文件的输入输出
参数说明:
pathname:含完整路径的文件名
flags:文件的打开方式 (O_RDONLY:只读 O_WRONLY:只写 O_RDWR:可读可写 暂先写这三个,其他的后面用到再说)
mode_t:新文件的存取权限
fd:文件描述符
buf:从文件中读取数据并存入 或 写入文件的数据 的首地址
count:要读取或者写入的数据大小
fildes:已打开文件的描述符
offset:移动读写位置的位移数
whence:文件读写指针相对于文件首的位置
1.创建
#include
#include
#include
int open(const char *pathname, int flags, mode_t mode),其中flags取O_CREAT
int creat(const char *pathname, mode_t mode) (creat只能以只写的方式创建文件,无法创建设备文件)
创建成功后,两个函数都返回文件的描述符,错误返回-1
2.打开
int open(const char *pathname, int flags)
返回值同上,头文件同上
3.关闭
#include
int close(int fd) (调用成功并不保证数据能全部写回硬盘)
调用成功返回0,失败返回-1
4.读取
#include
ssize_t read(int fd, void *buf, size_t count)
返回实际读取到的字节数,读到文件末尾(实际读取大小小于count)或者count为0时返回0,出错返回-1
5.写入
#include
ssize_t write(int fd, const void *buf, size_t count)
返回实际写入的字节数,出错返回-1
6.文件读写指针的移动
#include
#include
off_t lseek(int fildes, off_t offset, int whence) (若文件打开方式中包含添加,则读写位置指向文件末尾)
调用成功返回当前的读写位置,出错返回-1
常用方法:
移到文件开头:lseek(int fildes, 0, SEEK_SET);
移到文件末尾:lseek(int fildes, 0, SEEK_END);
移到当前位置:lseek(int fildes, 0, SEEK_CUR);
注意:设备文件不能使用lseek,Linux不允许lseek对tty设备进行操作.
文件锁的部分暂时空着.
五.文件属性操作
参数说明:
file_name:要操作的文件名
buf:存储文件状态信息的结构体地址
filedes:已打开文件的描述符
1.获取文件属性
#include
#include
#include
int stat(const char *file_name, struct stat *buf);
int fstat(int filedes, struct stat *buf);
int lstat(const char *file_name, struct stat *buf);
执行成功都返回0,失败返回-1
注意:lstat返回符号链接本身的状态,stat返回符号链接所指向的文件状态信息
struct stat结构体的常用成员:
st_mode,st_uid,st_gid,st_size,st_atime,st_mtime
判断文件类型:
S_IS(LNK,REG,DIR,CHR,BLK,FIFO,SOCK)
2.设置文件属性
存取权限:hmod/fchmod
用户id和组id:
#include
#include
int chown(const char *path, uid_t owner, gid_t group);
int fchown(int fd, uid_t owner, gid_t group);
int lchown(const char *path, uid_t owner, gid_t group);
f,l的作用与前面的一致
执行成功返回0,失败返回-1
改变文件大小:
#include
#include
int truncate(const char *path, off_t length);
int ftruncate(int fd, off_t length);
执行成功返回0,失败-1
改变任何文件的st_mtime域和st_ctime域:
#include
#include
int utime(const char *filename, struct utimbuf *buf);
utimbuf的定义如下:
struct utimbuf
{
time_t actime;
time_t modtime;
};
注意:如果buf是空指针,则两个时间均改为当前时间
设置文件创建时使用的屏蔽字:
#include
#include
mode_t umask(mode_t mask);
六.文件的移动和删除
1.文件的移动
#include
int reaname(const char *oldpath, const char *newpath);
若newpath是一个文件名,则改名;若newpath是一个目录名,则移动文件到该目录下,返回(0,-1)
注意:若newpath所指定的文件已经存在,则删除原文件
2.文件的删除
#include
int unlink(const char *pathname);
int remove(const char *pathname);
实际上remove封装了unlink.
七.目录操作
1.目录的创建
#include
#include
int mkdir(const char *pathname, mode_t mode);
2.目录的删除
#include
int rmdir(const char *pathname);
注意:rmdir只能删除指定的空目录,若要递归删除非空目录,则需要使用系统调用rm -r <目录名>,但是这个命令有一定的危险性(递归删除)!!
3.获取当前目录
#include
char *getcwd(char *buf, size_t size); 复制当前目录到buf所指空间,size为buf大小
char get_current_dir_name(void);
char *getwd(char *buf);
4.设置工作目录
#include
int chdir(const char *path); 将当前的工作目录改为由参数pah指定的目录
int fchdir(int fd);
5.获取目录信息
#include
#include
DIR *opendir(const char *name)
用于打开name指定的目录,并返回目录流(类似于文件描述符),失败返回NULL
struct dirent *readdir(DIR *dir);
用于从参数dir中读取出目录项信息
struct dirent 中常用的成员有long d_ino,存储目录的inode
int closedir(DIR *dir)
用于关闭参数dir指向的目录
---从ls中学到的知识点:
1.存储不同的命令行参数时(-参数),可以做或运算,原理就是用二进制的"位"来存储信息,这样后面在判断参数时可以做与运算.因此,定义对应的宏时应该定义为2的指数倍(二进制表示中只有一位不为0);
2.打印有一定顺序的数据时,若不要求将存储的文件更改顺序,只是打印出来的显示有顺序的话,当数据量较大时,可以定义一个动态的整型数组,用malloc申请空间,当排序时,可以仅仅交换各个数据的下标,打印时按排好序的下标打印,但是一定要注意用完动态数组后记得用free()释放存储空间,否则会造成内存泄露等严重问题;
3.使用函数int stat(const char *fila_name, struct stat *buf)时注意:参数fila_name必须是带完整路径的文件名或者是当前目录下的文件名,否则会出错,出错信息为:在当前目录下无该文件;
4.当我们使用终端系统命令时,若命令行参数为目录名时,我们可以只输入目录名,不用加上'/',原因是系统命令在执行时已经自动加上了(这个不太确定,也有可能是系统根据文件属性判断的,自己完全是根据书上ls的实现猜测的);
5.对于一些函数的重复调用中 "每次调用都需要用到上次调用完的值"的变量,可以定义全局变量,但一定注意,不到万不得已绝对不用全局变量;
6.linuxC中定义了一些宏用来限制相关变量的大小,如NAME_MAX是文件名可用的最大长度,PATH_MAX是目录名可用的最大长度,他们都包含在头文件linux/limits.h中;
7.struct stat结构体中文件的时间信息是一个字符类型的变量,因此输出时可用'%s';
8.判断某个文件是否有某种权限时,可以根据buf.st_mode跟对应的宏做与运算是否为0来判断(有则不为0);
9.在给字符数组或指针 直接复制字符串(不从其他地址复制) 时(如strcpy(str, "abcd");),记得给字符串末尾加上结束标志'\0',否则用字符串处理函数操作时可能会出错;
10.对目录的操作跟对文件操作类似:文件描述符对应目录流,创建文件(目录),打开文件(目录),读取文件数据(目录内容),关闭文件(目录).
阅读(1189) | 评论(0) | 转发(0) |