# 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; |
| } |