程序设计:C++ 一个用目录结构构建索引的类

文章介绍了如何使用C++实现的FastFileInex类,该类用于管理文件索引,通过利用文件系统目录结构对数据进行高效存储和访问,同时处理文件读写和删除操作。涉及到的类如sstring、CDir和CEasyFile也做了简要说明。

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

初级代码游戏的专栏介绍与文章目录-CSDN博客

我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。

这些代码大部分以Linux为目标但部分代码是纯C++的,可以在任何平台上使用。


        有时候可以利用文件系统目录结构对数据进行索引,将数据存储为小文件,避免在大文件里搜索。文件系统的目录结构本身是个树结构,相当于索引树,但每个目录下的文件数不能太多,因为目录下文件是遍历查找的,同时也不能太少,因为每个目录节点本身也要占用空间,海量目录占用空间巨大。

        本代码用字符串做key,若干个字节放一级目录(参数设置),如果设置为一个字节一级目录,那么key="123"的数据放置在“1/2/3/123.cache”文件里。

        代码如下:

	//快速文件索引,此结构本身可以放在共享内存
	class CFastFileInex
	{
	private:
		sstring<256> m_dir;//根目录
		long section;//几个字节一层目录,同一个目录下文件超过一定数量打开文件会很慢
	public:
		char const * GetRoot()const { return m_dir.c_str(); }
		string & toString(string & str)const
		{
			stringstream ss;
			ss << "dir[" << m_dir.c_str() << "]" << section;
			return str = ss.str();
		}
		void SetFastFileInex(char const * dir, long _section)
		{
			m_dir = dir;
			section = _section;
		}
		string & ffiGetFileName(unsigned long key, string & filename)const
		{
			char buf[256];
			sprintf(buf, "%lu", key);
			return ffiGetFileName(buf, filename);
		}
		string & ffiGetFileName(char const * key, string & filename)const
		{
			filename = m_dir.c_str();

			int len = strlen(key);
			long k = len / section;
			if (0 == len % section)--k;
			for (long i = 0; i < k; ++i)
			{
				for (long j = 0; j < section; ++j)	filename += key[i*section + j];
				filename += '/';
			}
			filename += key;
			filename += ".cache";
			return filename;
		}
		bool ffiReadFile(unsigned long key, CBuffer & buffer)const
		{
			char buf[256];
			sprintf(buf, "%lu", key);
			return ffiReadFile(buf, buffer);
		}
		bool ffiReadFile(char const * key, CBuffer & buffer)const
		{
			string filename;
			ffiGetFileName(key, filename);

			//打开失败再创建目录,再次打开失败才算失败
			CEasyFile file;
			if (!file.ReadFile(filename.c_str(), buffer))
			{
				CDir::CreateDir(filename.c_str());
				if (!file.ReadFile(filename.c_str(), buffer))
				{
					DEBUG_LOG << "打开文件出错 " << filename << " " << strerror(errno) << ende;
					return false;
				}
			}
			return true;
		}
		//读不到足够数据则失败
		bool ffiReadFile(long key, char * buffer, long buffersize)const
		{
			char buf[256];
			sprintf(buf, "%lu", key);
			return ffiReadFile(buf, buffer, buffersize);
		}
		//读不到足够数据则失败
		bool ffiReadFile(char const * key, char * buffer, long buffersize)const
		{
			string filename;
			ffiGetFileName(key, filename);

			//打开失败再创建目录,再次打开失败才算失败
			CEasyFile file;
			if (!file.ReadFile(filename.c_str(), buffer, buffersize))
			{
				CDir::CreateDir(filename.c_str());
				if (!file.ReadFile(filename.c_str(), buffer, buffersize))
				{
					DEBUG_LOG << "打开文件出错 " << filename << " " << strerror(errno) << ende;
					return false;
				}
			}
			return true;
		}
		bool ffiWriteFile(long key, char const * buffer, long buffersize)const
		{
			char buf[256];
			sprintf(buf, "%lu", key);
			return ffiWriteFile(buf, buffer, buffersize);
		}
		bool ffiWriteFile(char const * key, char const * buffer, long buffersize)const
		{
			string filename;
			ffiGetFileName(key, filename);

			//打开失败再创建目录,再次打开失败才算失败
			CEasyFile file;
			if (!file.WriteFile(filename.c_str(), buffer, buffersize))
			{
				CDir::CreateDir(filename.c_str());
				if (!file.WriteFile(filename.c_str(), buffer, buffersize))
				{
					DEBUG_LOG << "写入文件出错 " << filename << " " << strerror(errno) << ende;
					return false;
				}
			}
			return true;
		}
		bool ffiDeleteFile(long key)const
		{
			char buf[256];
			sprintf(buf, "%lu", key);
			return ffiDeleteFile(buf);
		}
		bool ffiDeleteFile(char const * key)const
		{
			string filename;
			ffiGetFileName(key, filename);

			//打开失败再创建目录,再次打开失败才算失败
			CEasyFile file;
			if (!file.DeleteFile(filename.c_str()))
			{
				DEBUG_LOG << "删除文件出错 " << filename << " " << strerror(errno) << ende;
				return false;
			}
			return true;
		}
	};

        里面用到的一些别的代码:

sstring 是个定长字符串模板类,替换成string就可以了

CDir 目录操作类,用到的函数的功能看名字就能理解了

CEasyFile 一个简单的文件接口类,用到的函数的功能看名字就能理解了


(这里是结束)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

初级代码游戏

知识究竟是有价还是无价

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值