天啊, 自己解析(listfile)本身就是一个错误!
因为StormLib在打开MPQ文件时就已经自己解析过了, 没必要多此一举!
而且, 虽然自己缓存一下文件树会加快查找和枚举的速度, 但是, 从字符串构造这个棵树的时间太长了~~~
这就导致了一个很严重的问题: 启动速度慢.......
对于文件树, 游戏没有什么用, 因为游戏读文件时根本不管是什么目录, 你可以把目录也看是文件名的一部分
换句话说, MPQ包里根本就没有目录的概念!
而对于编辑器等需要列举文件/文件夹列表的场合, 直接对所有文件进行枚举再判断字符串即可:
//------------------------------------------------------------------------------ Array<String> MpqArchive::ListFiles(const String& dirPathInMpqArchive, const String& pattern) { Array<String> result; String fileMask(dirPathInMpqArchive); fileMask.SubstituteChar('/', '//'); if (fileMask[fileMask.Length() - 1] != '//') { fileMask.Append("//"); } fileMask.Append(pattern); // start to find SFILE_FIND_DATA findData; BOOL found = TRUE; HANDLE fileHandle = SFileFindFirstFile(this->mpqFileHandle, fileMask.AsCharPtr(), &findData, NULL); while (0 != fileHandle && TRUE == found) { result.Append(String(findData.cFileName).ExtractFileName()); found = SFileFindNextFile(fileHandle, &findData); } return result; }
下面是我的"单元"测试程序(嘿嘿, 包装一个好听的名字), 运行一下不会超过2秒, DEBUG模式下
//------------------------------------------------------------------------------ // mpqfilesystemtest.cc // (C) 2008 xoyojank //------------------------------------------------------------------------------ #include "stdneb.h" #include "mpqfilesystemtest.h" #include "interface/iointerface.h" namespace Test { __ImplementClass(Test::MpqFileSystemTest, 'MQFT', Test::TestCase); using namespace IO; using namespace Interface; using namespace Util; //------------------------------------------------------------------------------ /** */ void MpqFileSystemTest::Run() { Ptr<IoServer> ioServer = IoServer::Create(); ioServer->SetZipFileSystemEnabled(false); ioServer->RegisterStandardUriSchemes(); ioServer->MountWoWMpqArchives(); //n_assert(ioServer->IsFileExsit("wow:Creature/Cat/Cat.m2")); Array<String> catFiles = ioServer->ListFiles("wow:Creature/Cat", "*.*"); for (IndexT i = 0; i < catFiles.Size(); ++i) { n_printf("%s/n", catFiles[i].AsCharPtr()); } Array<String> charDirs = ioServer->ListDirectories("wow:Character", "*"); for (IndexT i = 0; i < charDirs.Size(); ++i) { n_printf("%s/n", charDirs[i].AsCharPtr()); } URI uri = "wow:Character/BloodElf/HAIR00_00.blp"; Ptr<Stream> texture = ioServer->CreateStream(uri); texture->Open(); Array<char> buffer(texture->GetSize(), 0, 0); texture->Read(&buffer.Front(), texture->GetSize()); texture->Close(); } } // namespace Test