LINUX下文件的操作
以下均已为ubuntu 18.04 LTS环境。
-
文件的打开
open
-
打开文件的函数原型:
*open(const char pathname, int flags);
*open(const char pathname, int flags, mode_t mode);
-
打开文件函数需要的头文件:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
文件的打开需要文件的绝对或相对路径字符串,还有文件打开的方式。
一般常用有以下三种。
对应的标志 含义 O_RDONLHY 只读 O_WRONLY 只写 O_RDWR 读写 O_CREAT 文件不存在就创建这个文件(需要使用mode_t mode 参数进行文件权限的设置) O_TRUNC 文件存在并且以可写的形式打开时,此标志将会把文件长度清零,即原文件格式化 O_APPEND 写入的数据添加到文件的尾部 并且前三种的标志互相冲突,不可以同时进行只读、只写、读写操作
-
-
文件的读取
read
-
文件读取的函数原型:
*read(int fd, void buf, size_t count);
-
需要用到的头文件:
#include <unistd.h>
文件的读取需要注意的是每个参数的意义:
fd 对应的是 打开文件时的文件描述符,文件描述符对应的是一个int值。当打开文件失败时,open函数对应返回 -1 作为读取失败的标志。
buf 是文件读取写入的字符串。
count 为一次读取的字节个数。
-
-
文件的写入
write
-
文件写入的函数原型:
*write(int fd, const void buf, size_t count);
-
需要用到的头文件:
#include <unistd.h>
fd 对应的是 打开文件时的文件描述符,文件描述符对应的是一个int值。当打开文件失败时open函数对应返回 -1 作为读取失败的标志。
-
buf 是写入文件的字符串。
count 为一次写入的字节个数。
-
文件的关闭
close
-
关闭文件的原型:
close(int fd);
-
需要的头文件:
#include <unistd.h>
关闭文件的读取,只需要文件的描述符即可。关闭文件应在所有文件操作之后。
-
//利用以上文件的操作,可以完成对一个的复制功能。
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char **argv){
//成功读取的数据个数,设置为1 ,确保进入循环
int success = 1;
//文件描述符定义
int fd1;
int fd2;
//复制中转字符数组
char copy[100];
//argv[1]为要复制的文件名,argv[2]为复制的副本文件名
//先判断参数是否够
if(argc < 3){
printf("参数不够!\n");
}
//再打开文件
//打开文件失败
if((fd1 = open(argv[1], O_RDONLY)) == -1){
perror("open file1 failed\n");
exit(0);
}
if((fd2 = open(argv[2], O_WRONLY)) == -1){//在这个判断条件里文件描述符不能用括号括!!!!!
perror("open file2 failed\n");
}
// fd2 = open(argv[2], O_WRONLY);
while(success){
//成功读取的字符个数
//int sussess;
success = read(fd1, copy, 100);
write(fd2, copy, success);
}
//关闭两个文件
close(fd1);
close(fd2);
return 0;
}
-
文件指针的移动
lseek
-
指针移动函数的原型:
lseek(int fd, off_t offset, int whence);
-
需要的头文件
#include <sys/types.h>
#include <unistd.h>
移动的三种状态 操作及意义 SEEK_SET 将文件指针移动到文件的开始处,offset是指针相对SEEK_SET的偏移位置,所以此时offset只有正值,即只能向文件的末尾偏移。 SEEK_CUR 对于当前文件指针指向进行偏移,可正可负 SEEK_END 文件指针指向文件的尾部,只能读取负值,即向文件的开头偏移。
-
-
文件描述符的复制
dup,dup2
-
函数的原型:
int dup(int oldfd);
int dup2(int oldfd, int newfd);
-
所需的头文件:
#include <unistd.h>
函数 意义 dup()
返回一个和原先文件指针指向相同的地方,不管是新的指针移动,还是旧的指针移动,都会影响另外一个指针的移动,且未移动的指针与移动了的指针移动状态相同 dup2
自定义一个新的文件指针,且指针状态互不影响。
-
-
文件状态函数
fcntl
-
函数原型:
int fcntl(int fd, int cmd );
int fcntl(int fd, int cmd, long arg);
*int fcntl(int fd, int cmd, struct flock lock);
-
需要的头文件:
#include <unistd.h>
#include <fcntl.h>
cmd值 意义 F_DUPFD 可以复制文件的描述符 F_GETFD 获取文件描述符的close-on-exec标志 F_SETFD 用来设置文件描述符close-on-exec标志的第三个参数arg的最后一位。 F_GETFL 用来获得文件的打开方式 F_njSETFL 设置文件打开的第三个参数arg指定的方式
-
由fcntl
文件产生的文件记录锁。
*int fcntl(int fd, int cmd, struct flock lock);
//struct flock *lock结构体原型
struct flock {
short l_type;/*设置文件锁的状态 F_RDLCK|F_WRLCK|F_UNLCK*/
short l_whence;/*跟文件的移动SEEK_SET or SEEK_CUR or SEEK_END一样*/
off_t l_start;/*开始设置锁的位移*/
off_t l_len;/*设置锁的长度为多大*/
pid_t l_pid;/*锁的主进程PID*/
}
//根据锁的状态来设置文件锁,首先获得状态,是否可以加锁。可以,加锁。不可以,等待锁解开。
//同一个进程可以对锁的状态进行随意更改,但是不同进程之间,不可以随意更改。需要更改,首先要获得状态。
//首先对lock结构体进行填充,确定想要给锁加的状态。之后进行判断能否加锁。
lock.l_type = F_RDLCK;//设置读锁
lock.l_whence = SEEK_SET;//锁的偏移量起始位置
lock.l_start = 0;//
lock.l_len = 0;//锁的区域从0开始,到最大可能到的地方。
fcntl(fd, F_GETLK, lock);//进程试图获取文件是否可以加锁。
fcntl(fd, F_SETLK, lock);//设置文件锁
linux文件属性的操作
-
获取文件属性
通过stat结构体来获取
struct stat { dev_t st_dev; /* ID of device containing file */ ino_t st_ino; /* Inode number */ mode_t st_mode; /* 文件的类型和权限 */ nlink_t st_nlink; /* 硬链接的数目 */ uid_t st_uid; /* 用户所有者ID */ gid_t st_gid; /* 用户所在组ID */ dev_t st_rdev; /* Device ID (if special file) */ off_t st_size; /* 文件大小 */ blksize_t st_blksize; /* 文件所占块大小 */ blkcnt_t st_blocks; /*Since Linux 2.6, the kernel supports nanosecond precision for the following timestamp fields. For the details before Linux 2.6, see NOTES. */ struct timespec st_atim; /* 最后访问时间 */ struct timespec st_mtim; /* 最后修改时间 */ struct timespec st_ctim; /* 上次状态修改时间 */ #define st_atime st_atim.tv_sec /* Backward compatibility */ #define st_mtime st_mtim.tv_sec #define st_ctime st_ctim.tv_sec };
利用这个可以完美的将文件的信息打印出来。
//这是一个系统内部 举出来的例子 #include <sys/types.h> #include <sys/stat.h> #include <time.h> #include <stdio.h> #include <stdlib.h> #include <sys/sysmacros.h> int main(int argc, char *argv[]) { struct stat sb; if (argc != 2) { fprintf(stderr, "Usage: %s <pathname>\n", argv[0]); exit(EXIT_FAILURE); } if (lstat(argv[1], &sb) == -1) { perror("lstat"); exit(EXIT_FAILURE); } printf("ID of containing device: [%lx,%lx]\n", (long) major(sb.st_dev), (long) minor(sb.st_dev)); printf("File type: "); switch (sb.st_mode & S_IFMT) { case S_IFBLK: printf("block device\n"); break; case S_IFCHR: printf("character device\n"); break; case S_IFDIR: printf("directory\n"); break; case S_IFLNK: printf("symlink\n"); break; case S_IFREG: printf("regular file\n"); break; case S_IFSOCK: printf("socket\n"); break; default: printf("unknown?\n"); break; } printf("I-node number: %ld\n", (long) sb.st_ino); printf("Mode: %lo (octal)\n", (unsigned long) sb.st_mode); printf("Link count: %ld\n", (long) sb.st_nlink); printf("Ownership: UID=%ld GID=%ld\n", (long) sb.st_uid, (long) sb.st_gid); printf("Preferred I/O block size: %ld bytes\n", (long) sb.st_blksize); printf("File size: %lld bytes\n", (long long) sb.st_size); printf("Blocks allocated: %lld\n", (long long) sb.st_blocks); printf("Last status change: %s", ctime(&sb.st_ctime)); printf("Last file access: %s", ctime(&sb.st_atime)); printf("Last file modification: %s", ctime(&sb.st_mtime)); exit(EXIT_SUCCESS); } //详细的写了一个文件的具体信息。
st_mode利用了特征位来表示文件类型
S_IFMT
为位遮罩
可以利用st_mode & S_IFMT
最终判断文件的类型。也可以使用
宏 意义 S_ISLNK(st_mode) 判断文件是否为符号链接文件。 此外还有很多宏,对应判断不同的文件类型。
-
设置文件属性
-
文件权限的修改
chmod/fchmod
-
函数的原型:
*int chmod (const char pathname, mod_t mode)
int fchmod(int fd, mod_t mode)
-
需要的头文件:
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h> #include <stdlib.h> #include <sys/stat.h> int main(int argc, char **argv){ if(argc != 2){ exit(0); } chmod(argv[1], S_IRUSER|S_IWUSR|S_IXUSR|S_IRGRP);//-rwxr----- int fd = open(argv[1], O_RDWR); fchmod(fd, S_IRUSER|S_IWUSR|S_IXUSR|S_IRGRP);//-rwxr----- close(fd); }
-
-
文件所有者和所有组的修改:
chown/fchown/lchown
-
函数的原型:
*int chown(const char pathname, uid_t owner, gid_t group);
int fchown( int fd, uid_t owner, gid_t group);
*int lchown(const char pathname, uid_t owner, gid_t group);
-
需要的头文件:
#include <fcntl.h>
#include <unistd.h>
修改时,需要牢记修改的
UID
和GID
防止改错。
-
-
文件大小的修改
truccate/ftruccate
-
函数的原型:
*int truncate(const char path, off_t length);
int ftruncate(int fd, off_t length); -
需要的头文件:
#include <unistd.h>
#include <sys/types.h>
最好不要用,将文件修改小时,会丢失尾部数据,当文件修改大时,会将尾部数据有序性打乱。
-
-
文件时间的修改
utime
-
函数原型:
**int utime(const char filename, const struct utimbuf times)
*int utimes(const char filename, const struct timeval times[2]);
-
需要的头文件:
#include <sys/types.h>
#include <utime.h>#include <sys/time.h>
可以修改文件的
st_ctim``st_mtim
。- - utime 将第一个参数文件的存取时间改为第二个参数buf的actim域,把修改时间改为第二个参数buf的modtim域,如果buf为一个空指针,则都改为当前时间。 -
-
文件保留权限
umask
-
函数原型:
mode_t umask(mode_t mask);
-
需要的头文件:
#include <sys/types.h>
#include <sys/stat.h>
创建文件或目录的权限,
umak & st_mode
。参数mask为文件所有的权限。st_mode 为 S_IRUSR 等等。
-
-
文件的移动
rename
- 函数的原型:
**int rename(const char oldpath, const char newpath);
**int renameat(int olddirfd, const char oldpath, int newdirfd, const char newpath);
**int renameat2(int olddirfd, const char oldpath, int newdirfd, const char newpath, unsigned int flags);
-
需要的头文件:
#include <stdio.h>
#include <fcntl.h>
#include <stdio.h>
文件会将 oldpath 所描述的文件名称改为参数newpath。newpath下如果该文件已存在,则删除旧文件。
-
文件的删除
unlink/remove
-
函数的原型:
int unlink(const char *pathname);
//不懂 int unlinkat(int dirfd, const char *pathname, int flags);
-
需要的头文件:
include <unistd.h>
-
函数的原型:
int remove(const char *pathname);
-
需要的头文件:
include <stdio.h>
使用ulink时,在进程打开文件的时候,即使文件被销毁。但是接下来的对销毁文件的操作也成立。因为在进程的结束,即使因为销毁后还有对文件的操作,也不会缓存这个所有的文件。
-
-
目录的操作
mkdir/rmdir/getcwd/chdir/fchdir/opendir/readdir/closedir
-
mkdir
-
函数的原型:
*int mkdir(const char pathname, mode_t mode);
-
需要的头文件:
#include <sys/stat.h>
#include <sys/types.h>
创建一个文件夹,创建在pathname路径下。权限mode自己加。
-
-
rmdir
-
函数的原型:
*int rmdir(const char pathname);
-
需要的头文件:
#include <unistd.h>
删除指定路径下的文件。
-
-
getcwd
-
函数的原型:
**char getcwd(char buf, size_t size);
-
需要的头文件:
#include <unistd.h>
将当前工作目录的绝对路径复制到参数buf所指的内存空间。
-
-
chdir
-
函数的原型:
*int chdir(const char path);
int fchdir(int fd); -
需要的头文件:
#include <unistd.h>
改变当前的工作路径到指定的路径。
-
-
opendir
-
函数的原型:
**DIR opendir(const char name);
*DIR fdopendir(int fd); -
需要的头文件:
#include <sys/types.h>
#include <dirent.h>
根据路径或者文件描述符打开一个目录。 目录返回一个DIR类型的文件目录流。
-
-
readdir
-
函数的原型:
**struct dirent readdir(DIR dirp);
-
需要的头文件:
#include <dirent.h>
open目录返回的DIR目录指针参数,返回一个struct dirent类型的指针。里边存放文件的d_ino,d_reclen (d_name的长度),d_off不懂。
-
-
-
7. `closedir`
- 函数的原型:
**int closedir(DIR *dirp);**
- 需要的头文件
**#include <sys/types.h>**
**#include <dirent.h>**
根据文件目录流,关闭文件目录。
网友评论