1.定义
本章主要介绍一些和unix文件操作相关的结构体,例如stat,dirnet等
2.详解
2.1.stat简介
stat是文件类,主要作用是用来获取文件信息,其需要的头文件为#include<sys/types.h>,#include<sys/stat.h>,#include<unistd.h>
2.2.stat声明
我们使用struct stat buf声明一个stat变量,然后使用result = stat("a.txt", &buf)将stat和一个文件关联,当返回为1的时候为失败,否则表明创建成功
#include <iostream>
#include <ctime>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
using namespace std;
int main()
{
struct stat buf;
int result;
result = stat("a.txt", &buf);
if (result != 0)
{
printf("Failed\n");
}
else
{
printf("Successful\n");
}
}
下面我们简单介绍一下stat结构体中所包含的变量
struct stat {
dev_t st_dev; //文件所在磁盘驱动器号
ino_t st_ino; //inode,FAT、NTFS文件系统无意义
unsigned short st_mode; //文件、文件夹的标志
short st_nlink; //非NTFS系统上通常为1
short st_uid; //UNIX系统上为userid,windows上为0
short st_gid; //UNIX系统上为groupid,windows上为0
dev_t st_rdev; //驱动器号,与st_dev相同
off_t st_size; //文件字节数
blksize_t st_blksize; //系统块的大小
blkcnt_t st_blocks; //文件所占块数
time_t st_atime; //上次访问时间
time_t st_mtime; //上次修改时间
time_t st_ctime; //创建时间
};
我们写一个简单的例子将stat中的信息输出
#include <iostream>
#include <ctime>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
using namespace std;
int main()
{
struct stat buf;
int result;
result = stat("a.txt", &buf);
if (result != 0)
{
printf("Failed\n");
}
else
{
cout << "ID of device containing file:" << buf.st_dev << endl;
cout << "inode number:" << buf.st_ino << endl;
cout << "protection:" << buf.st_mode << endl;
cout << "number of hard links:" << buf.st_nlink << endl;
cout << "user ID of owner:" << buf.st_uid << endl;
cout << "group ID of owner:" << buf.st_gid << endl;
cout << "device ID:" << buf.st_rdev << endl;
cout << "blocksize for filesystem I/O:" << buf.st_blksize << endl;
cout << "number of blocks allocated:" << buf.st_blocks << endl;
cout << "size of the file in bytes: " << buf.st_size << endl;
cout << "time of creation of the file: " << ctime(&buf.st_ctime);
cout << "time of last modification of the file: " << ctime(&buf.st_mtime);
cout << "time of last access of the file: " << ctime(&buf.st_atime);
}
return 0;
}
结果如下:
2.3.dirnet简介
dirnet是文件夹类,主要的作用是用来获取文件夹信息,其需要头文件#include<dirnet.h>
2.4.dirnet声明
我们需要首先使用opendir打开一个文件夹获得一个DIR结构体,然后使用readdir(DIR)即可完成对dirnet的声明
#include <iostream>
#include <dirent.h>
int main()
{
DIR *D = opendir("corpus1");
if (!D) {
std::cout<<"No such directory:"<<D<<"; exiting"<<std::endl;
exit(1);
}
while (auto E = readdir(D)) {
……
}
return 0;
}
下面我们将简单介绍一下dirnet结构体中所包含的变量
struct dirent
{
long d_ino; /* inode number 索引节点号 */
off_t d_off; /* offset to this dirent 在目录文件中的偏移 */
unsigned short d_reclen; /* length of this d_name 文件名长 */
unsigned char d_type; /* the type of d_name 文件类型 */
char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最长255字符 */
}
我们写一个简单的例子将dirnet中的信息输出
#include <iostream>
#include <dirent.h>
int main()
{
DIR *D = opendir("corpus1");
if (!D) {
std::cout<<"No such directory:"<<D<<"; exiting"<<std::endl;
exit(1);
}
while (auto E = readdir(D)) {
std::cout<<"inode number:"<<E->d_ino<<std::endl;
std::cout<<"offset to this dirent:"<<E->d_off<<std::endl;
std::cout<<"length of this d_name:"<<E->d_reclen<<std::endl;
std::cout<<"the type of d_name:"<<(E->d_type==DT_DIR)<<std::endl;
std::cout<<"file name:"<<E->d_name<<std::endl;
}
return 0;
}
结果如下:
在这里面比较关键的是d_type,这里标记着文件类型,
enum
{
DT_UNKNOWN = 0, //未知类型
# define DT_UNKNOWN DT_UNKNOWN
DT_FIFO = 1, //管道
# define DT_FIFO DT_FIFO
DT_CHR = 2, //字符设备
# define DT_CHR DT_CHR
DT_DIR = 4, //目录
# define DT_DIR DT_DIR
DT_BLK = 6, //块设备
# define DT_BLK DT_BLK
DT_REG = 8, //常规文件
# define DT_REG DT_REG
DT_LNK = 10, //符号链接
# define DT_LNK DT_LNK
DT_SOCK = 12, //套接字
# define DT_SOCK DT_SOCK
DT_WHT = 14 //链接
# define DT_WHT DT_WHT
};
3.实例
下面我们将实现一个使用stat和dirnet实现对目录下所有文件查找,首先我们使用stat查看文件是否存在,然后检查如果文件属性为文件夹,将接着对文件夹向下搜索,如果为常规文件,将文件放入vector中代码如下
#include <dirent.h>
#include <iterator>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <vector>
#include <ctime>
#include <iostream>
char GetSeparator() {
return '/';
}
long GetEpoch(const std::string &Path) {
struct stat St;
if (stat(Path.c_str(), &St))
return 0; // Can't stat, be conservative.
return St.st_mtime;
}
std::string DirPlusFile(const std::string &DirPath,const std::string &FileName) {
return DirPath + GetSeparator() + FileName;
}
void ListFilesInDirRecursive(const std::string &Dir, long *Epoch,std::vector<std::string> *V, bool TopDir) {
auto E = GetEpoch(Dir);
if (Epoch)
if (E && *Epoch >= E) return;
DIR *D = opendir(Dir.c_str());
if (!D) {
printf("No such directory: %s; exiting\n", Dir.c_str());
exit(1);
}
while (auto E = readdir(D)) {
std::string Path = DirPlusFile(Dir, E->d_name);
if (E->d_type == DT_REG || E->d_type == DT_LNK)
V->push_back(Path);
else if (E->d_type == DT_DIR && *E->d_name != '.')
ListFilesInDirRecursive(Path, Epoch, V, false);
}
closedir(D);
if (Epoch && TopDir)
*Epoch = E;
}
int main()
{
std::vector<std::string> AllFiles;
ListFilesInDirRecursive("example", nullptr, &AllFiles, /*TopDir*/true);
for(auto ll:AllFiles)
{
std::cout<<"file is "<<ll<<std::endl;
}
return 0;
}
结果如下:
(未完待续)