我有一个MFC项目,给定了初始的根路径,该项目遍历每个文件,文件夹和子文件夹,然后在列表控件中向用户显示每个文件。由于这很容易成为一个相当漫长的操作,因此我有时会(通过处理单个消息泵队列)放弃对操作系统的控制,从而允许显示到目前为止发现的每个元素。现在来了棘手的部分...
我想让元素按它们的最后一个已知修改时间戳进行排序,(我认为)这需要某种插入排序技术。由于某些元素可能包含重复的时间戳,但是文件路径不同,并且我们将按时间戳进行排序(std::string
以的格式存储为MM:DD:YY hh:mm
),因此std::vector
似乎没有一个简单的标签可以胜任。同样,我不希望用户在开始对元素进行排序之前不让整个操作等待完成,因为等待的时间是未知的,并且就像我上面所说的那样,很容易变得很长以至于使任何人都没有耐心。
最后,我需要某种方法来保持插入到列表控件中的元素平均映射到容器上的排序操作,以便用户可以实时查看根路径的最新修改内容(和子内容)。
为了实现此目的,将使用什么合适的容器和算法?
这基本上是我现在正在做的事情:
void CFileSearchDlg::UpdateDirectoryList(std::string strRootPath)
{
CFilesystem fs; // Helper class which uses C++11 <filesystem> to iterate through file path entries
DWORD time = GetTickCount(); // Determines if we should yield control to the OS after a certain period of time
m_listView.DeleteAllItems(); // Clears all current elements from the list view control
/*
// CFilesystem::Search() takes in a root path and a lambda expression, and executes the expression for each
// element found within the root path, passing a basic_directory_entry<path> as a parameter to the lambda
// expression, and will continue to parse until no entries are left (or until we return false)...
*/
fs.Search(strRootPath, [&](CFilesystem::path_entry pe)
{
// This is primarily a Unicode project, so we need to convert the search results to an std::wstring
std::string path = pe.path().string();
std::wstring wpath;
wpath.assign(path.begin(), path.end());
// Get a Win32 handle to the file/folder, or display an error & exit
auto hFile = CreateFileA(path.c_str(), GENERIC_READ, NULL, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
MessageBoxA(NULL, "Failed to open file", path.c_str(), MB_OK | MB_ICONERROR);
return false; // Stop parsing
}
// Get the date & time attributes of the file/folder, or display an error & exit
TCHAR fileTime[MAX_PATH];
ZeroMemory(&fileTime, sizeof(TCHAR)* MAX_PATH);
auto ret = GetLastWriteTime(hFile, fileTime, MAX_PATH);
CloseHandle(hFile);
if (!ret) {
MessageBoxA(NULL, "Failed to get date & time attributes", path.c_str(), MB_OK | MB_ICONERROR);
return false; // Stop parsing
}
std::wstring strTime(fileTime);
/**************************************************
// THIS IS WHERE THE MAGIC IS SUPPOSED TO HAPPEN //
/*************************************************/
InsertPathItem(m_listView, wpath, strTime); // ... But how?
// Check if we should yield control to the operating system
auto tick = GetTickCount();
if (tick - time > 100) {
YieldControl();
time = tick;
}
// Continue to parse directory contents
return true;
}
);
}
编辑:完整的答案似乎是galinette(关于适当的STL容器)和foraidt(关于将视图与数据同步)的组合。
只需使用std::multimap
,其键类型为整数时间戳(最快的方式)或您建议的时间字符串,如果默认字符串排序保持时间戳顺序(这比较慢)
std::multimap<time_t, std::wstring>
或者
std::multimap<std::string, std::wstring>
插入:
myFileMap.insert(std::pair<time_t, std::wstring>(time,wPath));
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句