Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

如何根据这个库产生文件索引? #1

Open
Tu5039 opened this issue Apr 24, 2020 · 14 comments
Open

如何根据这个库产生文件索引? #1

Tu5039 opened this issue Apr 24, 2020 · 14 comments

Comments

@Tu5039
Copy link

Tu5039 commented Apr 24, 2020

目前正在阅读您的代码。
但是我仍未搞清楚如何调用接口以产生一个卷的文件索引,或者说如何产生 存储了卷内所有文件位置 的一个对象
希望能解答,谢谢。

@bzmework
Copy link
Owner

bzmework commented Apr 27, 2020 via email

@Tu5039
Copy link
Author

Tu5039 commented Apr 27, 2020

我现在已经成功使用Deviceiocontrol获取文件的句柄以及父句柄,目前使用的是C++ STL库的map<string fileReference, FileInfo* fileInfo>作为存储结构,在一百万文件中先遍历查找文件名test再生成查找结果的文件完整路径用时大概在2-3s左右(我设计的生成路径算法在所有文件的路径都被生成的情况下的复杂度为n*log(n),n来自于遍历所有文件,log(n)来自于查找文件对应的父级目录)。

//文件信息的结构
class FileInfo
{
public:
    string filename;
    string fileRef;
    string fileParentRef;
    string fullPath;
    string vol;
    FileInfo(string fn, string fr, string fpr, string c)
    {
        filename = fn;
        fileRef = fr;
        fileParentRef = fpr;
        fullPath = "";
        vol = c;
    }
    ~FileInfo() {};
};
//生成文件路径
void __buildPath(unordered_map<string, FileInfo*>& fileMap, FileInfo* f)
{
    unordered_map<string, FileInfo*>::iterator it = fileMap.find(f->fileParentRef);
    if (it == fileMap.end())
    {
        f->fullPath = f->vol + ":\\" + f->filename;

    }
    else
    {
        if ((*it).second->fullPath == "")
        {
            __buildPath(fileMap, (*it).second);//在生成路径时,同时生成所有祖宗节点的路径,这样同级文件以及子文件的生成用时会降低。
        }
        f->fullPath = (*it).second->fullPath + "\\" + f->filename;
    }
}

在自己设计的字典结构的插入与访问速度能超越stl库的map/unordered_map之前,我认为map和unordered_map都是很不错的选择。
但这也是我设计的目的与您有所出入,我对性能和效率没有极致的需求。
我现在遇到的另一个问题是如何实时监控文件的变化(例如新建了一个文件、重命名文件),并将之添加到我的数据库中而不需要重新遍历USN信息。

@bzmework
Copy link
Owner

bzmework commented Apr 28, 2020 via email

@bzmework
Copy link
Owner

bzmework commented Apr 28, 2020 via email

@Tu5039
Copy link
Author

Tu5039 commented Apr 28, 2020

由于我打算用qt来完成界面,并且qt的tableView自带排序功能,我并没有太多地去考虑排序算法的问题。
但如果要我从零开始设计的话,我不完全认为归并排序是最优的选择:对于文件名、文件路径这两个字符串的排序,我认为归并排序、快排(或者改进的内省排序)都是很不错的选择;同时对于文件路径,我认为这一项里的拥有相同的头部字符子串的可能性更大,也就是说有序的可能性会更大?(这点我不是很确定)而在基本有序的情况下,插入排序更好。对于日期类的创建日期和修改日期,分治处理年月日,三者的波动范围并不大,很适合桶排序。文件大小则是难以有特征的随机数据,我倾向于快排。
对于归并排序,特别是大数据量下使用归并排序,我认为内存拷贝对于性能的影响更大,这也是虽然归并排序算法和快排是同一复杂度的算法时快排的表现往往更好的原因。
我不知道多线程对各种排序算法的影响有多大,以上只是对单线程排序的看法。具体参考百万级数据如何排序
监控方法已看到,我在完成后如果有时间的话会加入进来。
另外,dictionary和map的性能比较我也会在空余时间完成后继续回复。

@bzmework
Copy link
Owner

bzmework commented Apr 28, 2020 via email

@Tu5039
Copy link
Author

Tu5039 commented Apr 28, 2020

是的

@djbone
Copy link

djbone commented Oct 27, 2020

感觉我理解的对不对?这个程序只扫描了USN,USN只是增量的文件。是不是应该先读取MFT中的文件列表就可以了?USN只是为了后续文件变更快速更新索引,如果对实时性要去不高,其实是可以直接重新读取一次MFT?

@Tu5039
Copy link
Author

Tu5039 commented Oct 28, 2020

感觉我理解的对不对?这个程序只扫描了USN,USN只是增量的文件。是不是应该先读取MFT中的文件列表就可以了?USN只是为了后续文件变更快速更新索引,如果对实时性要去不高,其实是可以直接重新读取一次MFT?

我现在的处理方式就是你说的这样的。
有一个简陋的demo,如果需要的话我可以提供。

@djbone
Copy link

djbone commented Oct 29, 2020

好像可以参考ntfs-search里面是有,不过,我的疑问是你说ntfs-search速度比较慢,是说哪里慢?我觉得好像还可以,是加载速度慢,还是说搜索的过程慢?还是说搜索内容和ui绑定慢?

@Tu5039
Copy link
Author

Tu5039 commented Oct 29, 2020

好像可以参考ntfs-search里面是有,不过,我的疑问是你说ntfs-search速度比较慢,是说哪里慢?我觉得好像还可以,是加载速度慢,还是说搜索的过程慢?还是说搜索内容和ui绑定慢?

我不是很清楚你说的ntfs-search是哪个。
但如果是我之前的回复里说的效率低,主要有几个点:1. 当文件数据条目过多时,读入速度慢,这是不可避免的;2. 对建立文件的路径信息等派生信息需要时间,并且这个建立算法会极大地影响效率;以上两点均可以通过建立数据库来解决。

@djbone
Copy link

djbone commented Oct 29, 2020

https://github.com/aliakseis/NTFS-Search 我说的是这个,Fast-search首页作者说它比较慢,“在国内或者国外都有优秀的文件快速搜索程序,但开源的很少,网络上的源码大多数仅停留在基本的如何操作USN读取文件的层面, 出于商业目的,对具体的文件排序、文件压缩、文件索引、UI虚拟呈现等算法没有人愿意开源分享, 目前,能找到的开源程序有:https://sourceforge.net/projects/swiftsearch/https://sourceforge.net/projects/ntfs-search/ 但是,前者SwiftSearch采用异步IO扫描但源码可读性很差,而NTFS Search速度太慢,并且作者在其发布的新版中, 采用了内存映射技术,令扫描出来的文件占用内存较少,然而作者敝帚自珍,不再公布源码。“ 这段

@Tu5039
Copy link
Author

Tu5039 commented Oct 29, 2020

Emm...我对ntfs-search这个项目了解不多。
单以我完成我的Demo的经验来讲,整个项目可以划分为三个主要的部分:1. USN读取模块、2. Search-Demo搜索模块、3. UI界面设计。
其中,USN读取模块使用的是微软提供的API,个人开发者很难再大幅提升性能。当然,组织能力好的话,设计一个好的数据结构来存取USN读取到的数据也会有帮助。
第二部分则是可操作性最强的地方了。搜索采用kmp算法是必然的,我在我的Demo中是遍历所有文件名并且kmp判断是否和关键词匹配。但这应该还不是最优解,可能可以用散列、映射等的方法来替换遍历所有文件名的做法,又或者是对文件名先做一个预处理,如将含有不同字符的文件名分类等,没有实践过,对程序效率的提升效果不清楚,空间则应该会占用更多一点,如何取舍还需要在实践时考虑。
第三部分也是个人开发者无需花费太多精力的部分。
第一、二部分间还有个步骤1.5.处理USN数据。USN数据中最关键的是Parent Index(父目录索引Pi)和Child Index(自身索引Ci),一个Ci只有一个Pi,根目录没有Pi,需要根据两个索引来构造文件的完整路径。文件路径构建算法对于开发者来说也是值得下一番功夫的。我是将整个文件系统当成一棵树来构造,目前需要处理的文件F,当它的存在Pi时,他的路径就是Pi的路径加上它自身的文件名,依此递归处理,当递归到Pi对应的文件的路径已经被生成或者不存在Pi时停止递归。涉及到的几个地方:1. Pi、Ci、文件名FileName间选用什么数据结构来存储有利于存取数据?2. 选用什么算法来生成路径(如何进一步优化文件路径生成算法?) 3. USN中读取到的数据应选用多少项最有利于处理?如何处理USN中读到的raw数据以供程序使用?等 都值得考虑。
至于文件排序,同之前的回复一样,我认为在没有预处理的情况下,多线程归并排序应该就是最优解了。
我之前只是用来应付课设,所以研究仅限于此。

@pandatest2023
Copy link

我现在已经成功使用Deviceiocontrol获取文件的句柄以及父句柄,目前使用的是C++ STL库的map<string fileReference, FileInfo* fileInfo>作为存储结构,在一百万文件中先遍历查找文件名test再生成查找结果的文件完整路径用时大概在2-3s左右(我设计的生成路径算法在所有文件的路径都被生成的情况下的复杂度为n*log(n),n来自于遍历所有文件,log(n)来自于查找文件对应的父级目录)。

//文件信息的结构
class FileInfo
{
上市:
    字符串文件名;
    字符串fileRef;
    字符串fileParentRef;
    字符串fullPath;
    弦卷
    FileInfo(字符串fn,字符串fr,字符串fpr,字符串c)
    {
        文件名= fn;
        fileRef = fr;
        fileParentRef = fpr;
        fullPath = “ ” ;
        vol = c;
    }
    〜FileInfo(){};
};
//生成文件路径
void __buildPath(unordered_map<string, FileInfo*>& fileMap, FileInfo* f)
{
    unordered_map <string,FileInfo *> :: iterator = FileMap。查找(f-> fileParentRef);
    如果(它== fileMap。端())
    {
        f-> fullPath = f-> vol + “:\\ ” + f->文件名;

    }
    其他
    {
        如果((*它)。第二- > FULLPATH == “ ”)
        {
            __buildPath(fileMap, (*it).second);//在生成路径时,同时生成所有祖宗节点的路径,这样同级文件以及子文件的生成用时会降低。
        }
        f-> fullPath =(* it)。第二-> fullPath + “ \\ ” + f->文件名;
    }
}

在自己设计的字典结构的插入与访问速度能超越stl库的map/unordered_map之前,我认为map和unordered_map都是很不错的选择。
但这也是我设计的目的与您有所出入,我对性能和效率没有极致的需求。
我现在遇到的另一个问题是如何实时监控文件的变化(例如新建了一个文件、重命名文件),并将之添加到我的数据库中而不需要重新遍历USN信息。

您好 我也有这个需要 ,您可以共享代码吗

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants