C++ 文件操作

本文深入探讨了Unix系统下的文件和目录操作,详细介绍了stat结构体用于获取文件信息,包括文件大小、权限、时间戳等,以及dirnet结构体用于读取目录内容,展示了如何递归遍历目录并收集所有文件路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

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

结果如下:

(未完待续)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值