赞
踩
在 Linux 系统中必须要使用系统提供的 IO 函数才能基于这些文件描述符完成对相关文件的读写操作。
open/close:
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> /* open是一个系统函数, 只能在linux系统中使用, windows不支持 fopen 是标准c库函数, 一般都可以跨平台使用, 可以这样理解: - 在linux中 fopen底层封装了Linux的系统API open - 在window中, fopen底层封装的是 window 的 api */ // 打开一个已经存在的磁盘文件 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 #include <unistd.h> int close(int fd);
read/write
#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); 参数: fd: 文件描述符,open () 函数的返回值,通过这个参数定位打开的磁盘文件 buf: 指向一块有效的内存地址,里边有要写入到磁盘文件中的数据 count: 要往磁盘文件中写入的字节数,一般情况下就是 buf 字符串的长度,strlen (buf) 返回值: 大于 0: 成功写入到磁盘文件中的字节数 -1: 写文件失败了
上述函数使用
// 文件的拷贝 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <fcntl.h> int main() { // 1. 打开存在的文件open.txt, 读这个文件,注意文件的路径 int fd1 = open("./open.txt", O_RDONLY); if(fd1 == -1) { perror("open-readfile"); return -1; } // 2. 打开不存在的文件, 将其创建出来, 将从open.txt读出的内容写入这个文件中 int fd2 = open("bak.txt", O_WRONLY|O_CREAT, 0664); if(fd2 == -1) { perror("open-writefile"); return -1; } // 3. 循环读文件, 循环写文件 char buf[1024]; int len = -1; while( (len = read(fd1, buf, sizeof(buf))) > 0 ) { // 将读到的数据写入到另一个文件中 write(fd2, buf, len); } // 4. 关闭文件 close(fd1); close(fd2); return 0; }
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 <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,文件被截断,尾部多余的部分被删除,文件最终长度为 length
文件原来 size < length,文件被拓展,文件最终长度为 length
返回值:成功返回 0; 失败返回值 - 1
stat/lstat 函数
#include <sys/types.h> #include <sys/stat.h> #include <unistd.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; // inode节点 mode_t st_mode; // 文件的类型和存取的权限, 16位整形数 -> 常用 nlink_t st_nlink; // 连到该文件的硬连接数目,刚建立的文件值为1 uid_t st_uid; // 用户ID gid_t st_gid; // 组ID dev_t st_rdev; // (设备类型)若此文件为设备文件,则为其设备编号 off_t st_size; // 文件字节数(文件大小) --> 常用 blksize_t st_blksize; // 块大小(文件系统的I/O 缓冲区大小) blkcnt_t st_blocks; // block的块数 time_t st_atime; // 最后一次访问时间 time_t st_mtime; // 最后一次修改时间(文件内容) time_t st_ctime; // 最后一次改变时间(指属性) }; 获取文件属性实例: #include <sys/stat.h> int main() { // 1. 定义结构体, 存储文件信息 struct stat myst; // 2. 获取文件属性 open.txt int ret = stat("./open.txt", &myst); if(ret == -1) { perror("stat"); return -1; } printf("文件大小: %d\n", (int)myst.st_size); return 0; }
opendir/readdir/closedir 函数
#include <sys/types.h> #include <dirent.h> // 打开目录 DIR *opendir(const char *name); 参数: name -> 要打开的目录的名字 返回值: DIR*, 结构体类型指针。打开成功返回目录的实例,打开失败返回 NULL 目录打开之后,就可以通过 readdir () 函数遍历目录中的文件信息了。每调用一次这个函数就可以得到目录中的一个文件信息,当目录中的文件信息被全部遍历完毕会得到一个空对象。先来看一下这个函数原型: // 读目录 #include <dirent.h> struct dirent *readdir(DIR *dirp); 参数:dirp -> opendir () 函数的返回值 返回值:函数调用成功,返回读到的文件的信息,目录文件被读完了或者函数调用失败返回 NULL 函数返回值 struct dirent 结构体原型如下: struct dirent { ino_t d_ino; /* 文件对应的inode编号, 定位文件存储在磁盘的那个数据块上 */ off_t d_off; /* 文件在当前目录中的偏移量 */ unsigned short d_reclen; /* 文件名字的实际长度 */ unsigned char d_type; /* 文件的类型, linux中有7中文件类型 */ 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/test"); struct dirent* ptr = NULL; // 遍历目录 while( (ptr=readdir(dir)) != NULL) { ....... } 目录操作完毕之后,需要通过 closedir() 关闭通过 opendir() 得到的实例,释放资源。函数原型如下: // 关闭目录, 参数是 opendir() 的返回值 int closedir(DIR *dirp); 参数:dirp-> opendir () 函数的返回值 返回值:目录关闭成功返回 0, 失败返回 -1
目录函数实例说明–遍历目录:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <dirent.h> int getMp3Num(const char* path) { // 1. 打开目录 DIR* dir = opendir(path); if(dir == NULL) { perror("opendir"); return 0; } // 2. 遍历当前目录 struct dirent* ptr = NULL; int count = 0; while((ptr = readdir(dir)) != NULL) { // 如果是目录 . .. 跳过不处理 if(strcmp(ptr->d_name, ".")==0 || strcmp(ptr->d_name, "..") == 0) { continue; } // 假设读到的当前文件是目录 if(ptr->d_type == DT_DIR) { // 目录 char newPath[1024]; sprintf(newPath, "%s/%s", path, ptr->d_name); // 读当前目录的子目录 count += getMp3Num(newPath); } else if(ptr->d_type == DT_REG) { // 普通文件 char* p = strstr(ptr->d_name, ".mp3"); // 判断文件后缀是不是 .mp3 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[]) { // ./a.out path if(argc < 2) { printf("./a.out path\n"); return 0; } int num = getMp3Num(argv[1]); printf("%s 目录中mp3文件个数: %d\n", argv[1], num); return 0; }
到处就完成了基本函数的说明。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。