# Linux 文件操作
# Open
通过 Open 函数打开一个磁盘文件,如果不存在还可以打开新的文件
| #include <sys/type.h> |
| #include <sys/stat.h> |
| #include <fcntl.h> |
| |
| 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 : 以 读写 方式打开文件可选属性 ,和上边的属性一起使用O_APPEND : 新数据 追加到文件尾部 ,不会覆盖文件的原来内容O_CREAT : 如果文件 不 存在, 创建该文件 ,如果文件存在什么也不做O_EXCL : 检测 文件 是否 存在, 必须 要和 O_CREAT 一起使用,不能单独使用: O_CREAT | O_EXCL- 检测到文件
不 存在,创建新文件 - 检测到文件已经存在,创建失败,函数直接返回 - 1(如果不添加这个属性,不会返回 - 1)
mode :在创建新文件需要 指定新文件 的权限
* 参数最大值`0777`
* 返回值
* 成功:返回内核分配的文件描述符,大于0的整数
* 失败:-1
# Close 函数原型
释放 Open 函数打开的文件描述符
| #include <unistd.h> |
| int close(int fd); |
- 函数参数
:fd文件描述符 ,是 open () 函数的返回值 - 释放成功返回
0 ,调用 失败 返回 -1
# 测试
# 打开文件
授予 文件权限
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <string.h> |
| #include <fcntl.h> |
| |
| int main(void) |
| { |
| |
| int fd = open("a.txt", O_RDWR); |
| |
| |
| if (fd == -1) |
| { |
| printf("file open fail\n"); |
| } |
| else |
| { |
| printf("create file successful fd:%d\n", fd); |
| } |
| close(fd); |
| return 0; |
| } |
# 判断文件状态
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <string.h> |
| #include <fcntl.h> |
| |
| int main(void) |
| { |
| |
| int fd = open("./new.txt", O_CREAT | O_EXCL | O_RDWR); |
| if (fd == -1) |
| { |
| printf("file open fail\n"); |
| } |
| else |
| { |
| printf("create file successful fd:%d\n", fd); |
| } |
| close(fd); |
| return 0; |
| } |
# read
用于读取文件 内部 数据,在 Open 打开文件的时候 指定读权限
| #include <unistd.h> |
| ssize_t read(int fd,void *buf,size_t count); |
# 参数
- fd:文件描述符,open () 函数的返回值,通过这个参数定位打开的
磁盘文件 - buf: 是一个
传出参数 ,指向 一块有效的内存 ,用于 存储 从文件中 读出 的数据- 传出参数:类似于返回值,将变量地址传递给函数,函数调用完毕,地址中就有数据
- count :buf 指针指向的
内存的大小 ,指定可以存储的最大字节数
# 返回值
大于0 :从文件中读出的字节数, 读文件成功等于0 :代表文件读完, 读文件成功-1 : 读 文件失败
# write
将数据 写入 到文件 内部 ,通过 Open 打开文件的时候需要指定写权限
| #include <unistd.h> |
| ssize_t write(int fd,const void *buf,size_t count); |
# 文件拷贝
首先在目录中创建 english.txt文件
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <unistd.h> |
| #include <fcntl.h> |
| |
| int main(void) |
| { |
| |
| int fd1 = open("./english.txt", O_RDONLY); |
| if (fd1 == -1) |
| { |
| perror("open-readfile"); |
| return -1; |
| } |
| |
| |
| int fd2 = open("copy.txt", O_WRONLY | O_CREAT, 0664); |
| if (fd2 == -1) |
| { |
| perror("open-writefile"); |
| return -1; |
| } |
| |
| |
| char buf[4096]; |
| int len = -1; |
| while ((len = read(fd1, buf, sizeof(buf))) > 0) |
| { |
| |
| write(fd2, buf, |
| ); |
| } |
| |
| close(fd1); |
| close(fd2); |
| |
| return 0; |
| } |
# lseek 移动文件指针
lseek 可以通过此 函数移动 文件 指针
| #include <sys/types.h> |
| #include <unistd.h> |
| |
| off_t lseek(int fd,off_t offset,int whence); |
# 参数
- fd:文件描述符,open 函数的返回值
offset : 偏移量whence : 通过这个参数指定函数实现功能SEEK_SET :从文件 头部开始 偏移 offset 个字节SEEK_CUR : 从当前文件 指针的位置向后 偏移 offset 个字节SEEK_END : 从文件尾部 向后 偏移 offset 个字节
- 返回值
- 成功:文件指针
从头部 开始计算总的偏移量 - 失败:-1
| lseek(fd,0,SEEK_SET); |
| lseek(fd,0,SEEK_CUR); |
| lseek(fd,0,SEEK_END); |
# 扩展实现
| |
| #include <stdio.h> |
| #include <fcntl.h> |
| #include <unistd.h> |
| int main() |
| { |
| int fd = open("hello.txt",O_RDWR); |
| if(fd == -1) |
| { |
| perror("open"); |
| return -1; |
| } |
| |
| lseek(fd,1000,SEEK_END); |
| write(fd," ",1); |
| |
| close(fd); |
| return 0; |
| } |
# trucate/ftruncate
截断或扩展文件
| #include <unistd.h> |
| #include <sys/types.h> |
| int truncate(const char*path,off_t length); |
| int ftruncate(int fd,off_t length); |
# 参数:
- path:要
扩展/截断 的文件的文件名 - fd: 文件描述符,open () 得到
- length: 文件的
最终 大小size > length ,文件被 截断 ,尾部多余部分被删除size < length 文件被 拓展 ,文件最终长度为 length
- 返回值:成功返回 0 ,失败返回值 -1
# perror
返回值来描述系统 函数的状态 (调用是否成功) 成功返回 0,失败返回 - 1.
| #include <stdio.h> |
| |
| void perror(const char *s); |
| |
# 查看文件属性信息
file 文件名 [参数]
# 参数
-b 只显示文件类型和文件编码,不显示文件名-i 显示文件的 MIME 类型 MIME (Multipurpose Internet Mail Extensions) 多用途互联网邮件扩展类型-F 设置输出字符串的 分隔符-L 查看 软链接 文件自身文件属性
# stat 命令
显示文件或目录的 详细属性 信息和文件系统状态,输出的更加详细
# 参数
-f 仅显示文件 所在文件系 统的信息-L 查看 软链接 文件-c 查看文件 某个属性 信息-t 简洁模式,只 显示摘要 信息,不显示属性描述
# 输出的信息属性
* File :文件名
Size : 文件大小,单位字节Blocks : 文件使用的数据库总数IO Block :IO 块大小regular file : 文件的实际类型,文件类型不同,该关键字也会变化Device : 设备编号Inode : Inode 号,操作系统用 inode 编号来识别不同的文件,找到文件数据所在的 block 读出数据Links : 硬链接计数
* Access : 文件所有者 + 所属组用户 + 其他人对文件的访问权限Uid : 文件所有者名字和所有者 IDGid : 文件所有数组名字已经组 IDAccess Time : 表示文件的最后访问时间,Modify Time : 表示文件内容的最后修改时间Change Time : 文件的状态休息,被修改则更新,例如文件的硬链接链接数,大小,权限等Birth :文件生成日期
# stat/lstat 函数
lstat() :得到的是 软链接 文件本身的 属性信息
stat() : 得到的是 软链接 文件 关联 的文件的属性信息
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <unisd.h> |
| |
| int stat(const char *pathname ,struct stat *buf); |
| int lstat(const char *pathname,struct stat *buf); |
# 参数
pathname : 文件名,要获取这个文件的 属性信息buf : 传出参数 ,文件的信息被 写入 到这块内存中返回值 :成功返回 0 ,失败返回 -1 .
| struct stat { |
| dev_t st_dev; |
| ino_t st_ino; |
| mode_t st_mode; |
| nlink_t st_nlink; |
| uid_t st_uid; |
| gid_t st_gid; |
| dev_t st_rdev; |
| off_t st_size; |
| blksize_t st_blksize; |
| blkcnt_t st_blocks; |
| time_t st_atime; |
| time_t st_mtime; |
| time_t st_ctime; |
| }; |
# 读取文件大小
| #include <sys/stat.h> |
| #include <stdio.h> |
| int main(void) |
| { |
| |
| struct stat myst; |
| int ret = stat("./english.txt", &myst); |
| if (ret == -1) |
| { |
| perror("stat error"); |
| } |
| printf("文件大小为:%d\n", (int)myst.st_size); |
| return 0; |
| } |
# 目录遍历
# Opendir 函数打开目录
| #include <sys/types.h> |
| #include <dirent.h> |
| |
| DIR *opendir(const char *name); |
- 参数:
name 要打开的目录名字 - 返回值
DIR* , 结构体类型指针,打开失败返回 NULL
# readdir
目录打开后,通过 readdir () 函数 遍历目录中的 文件信息。
每调用一次 这个函数就可以得到目录中的一个 文件信息 ,当目录中的文件信息被 全部遍历 完毕会得到一个 空对象
| #include <dirent.h> |
| struct dirent *readdir(DIR *dirp) |
# 参数
dirp->opendir() 函数的返回值- 函数调用
成功 ,返回读到的文件的信息,目录文件被读完或者函数 调用失败 返回 NULL
# struct dirent 结构体原型
| struct dirent { |
| ino_t d_ino; |
| off_t d_off; |
| unsigned short d_reclen; |
| unsigned char d_type; |
| char d_name[256]; |
| }; |
- 结构体中文件类型
d_type 的宏值
DT_BLK :块设备文件
DT_CHR :字符设备文件
DT_DIR :目录文件
DT_FIFO :管道文件
DT_LNK :软连接文件
DT_REG :普通文件
DT_SOCK :本地套接字文件
DT_UNKNOWN :无法识别的文件类型 - 通过 readdir () 函数
遍历 某个目录中的文件
| |
| DIR* dir = opendir("/home/foryouos"); |
| struct dirent* ptr = NULL; |
| |
| while((ptr = readdir(dir)) != NULL) |
| { |
| |
| } |
# closedir
目录操作完毕之后,需要通过 closedir()关闭 通过 opendir () 得到的示例,释放资源
# 遍历单层目录
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <string.h> |
| #include <dirent.h> |
| |
| int main(int argc, char* argv[]) |
| { |
| DIR* dir = opendir(argv[1]); |
| if (dir == NULL) |
| { |
| perror("opendir NULL"); |
| return -1; |
| } |
| |
| int count = 0; |
| while (1) |
| { |
| struct dirent* ptr = readdir(dir); |
| if (ptr == NULL) |
| { |
| printf("目录读完了...\n"); |
| break; |
| } |
| |
| if (ptr->d_type == DT_REG) |
| { |
| char* p = strstr(ptr->d_name, ".txt"); |
| if (p != NULL && *(p + 4) == '\0') |
| { |
| count++; |
| printf("file %d: %s\n", count, ptr->d_name); |
| } |
| } |
| } |
| printf("%s目录中txt文件的格式:%d\n", argv[1], count); |
| closedir(dir); |
| return 0; |
| } |
# 遍历多层目录
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <string.h> |
| #include <dirent.h> |
| |
| int GetFile(const char* path) |
| { |
| DIR* dir = opendir(path); |
| if (dir == NULL) |
| { |
| perror("opendir NULL"); |
| return -1; |
| } |
| |
| struct dirent* ptr = readdir(dir); |
| int count = 0; |
| while ((ptr = readdir(dir)) != NULL) |
| { |
| |
| if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) |
| { |
| continue; |
| } |
| else if (ptr->d_type == DT_DIR) |
| { |
| |
| char newPath[4096]; |
| sprintf(newPath, "%s/%s", path, ptr->d_name); |
| count += GetFile(newPath); |
| } |
| else |
| { |
| |
| char* p = strstr(ptr->d_name, ".txt"); |
| if (p != NULL && *(p + 4) == '\0') |
| { |
| count++; |
| printf("%s/%s\n", path, ptr->d_name); |
| } |
| } |
| |
| } |
| closedir(dir); |
| return count; |
| |
| } |
| |
| int main(int argc, char* argv[]) |
| { |
| if (argc < 2) |
| { |
| printf("./a.out path\n"); |
| return 0; |
| } |
| int num = GetFile(argv[1]); |
| printf("%s .c :%d\n", argv[1], num); |
| return 0; |
| } |