Everything是个十分方便的本地文件搜索软件,谁用谁知道…一般每次启动后,它会有个初始化时间,初始化完成后,每次搜索,结果秒出。
有一篇文章是讲Everything实现原理的,详情勐戳此处
大体意思是,ntfs磁盘分区会有一个觉usn的日志系统,从这个日志系统中可以拿到类似全盘索引之类的数据,然后搜索时从这个数据格式出发,效率会比较高。但有个致命点是fat32格式的分区并没有这个usn系统,而且usn系统会返回所有相关的文件信息,不灵活。我的分区全是ntfs的,没有测试everything是否支持fat32,我想应该也是支持的,不过关对于fat32,Everything应该是使用了其他的方案。
起始基于初始化+N次搜索的思想,完全可以不实用usn这个东西。在第一次启动的时候,做一次全盘扫描,建立全盘文件索引到数据库。之后开一个线程监控磁盘,当发生文件的增加、修改、删除时,同步到数据库中。在每次搜索时,从数据库中查找,也是可以的。这样就不必要求磁盘必须是usn的。另外,可以灵活的选择需要哪些文件信息。
下面先使用python实现了这个思想,数据库使用的sqlite3,暂时没有开监控线程。数据库暂时没有优化。
#coding=utf-8
import os
import sqlite3
import time
#全局变量,记录文件数目
global file_number
#遍历disk磁盘
def all_files(disk):
global file_number
print “建立”+disk+”盘索引…”
dir_path = disk+”:”
for root ,subdirs, files in os.walk(dir_path):
for file in files:
filefullpath = os.path.join(root,file)
print ‘file_path: ‘+filefullpath+’ file_name: ‘+file+”\n”
insert_to_db(filefullpath,file)
file_number += 1
print disk+”盘索引建立完成”
#创建db
def create_db():
sqlite_con = sqlite3.connect(‘d:/mydatabase.db’)
sqlite_cur = sqlite_con.cursor()
sqlite_cur.execute(‘CREATE TABLE FOO (o_id INTEGER PRIMARY KEY, file_path VARCHAR(260), file_name VARCHAR(260))’)
sqlite_con.commit
#插入记录到db
def insert_to_db(file_path,file_name):
con = sqlite3.connect(‘d:/mydatabase.db’)
cur = con.cursor()
cur.execute(‘INSERT INTO foo (o_id, file_path, file_name) VALUES(NULL, ?, ?)’,[file_path.decode(‘gbk’),file_name.decode(‘gbk’)])
con.commit()
#初始化数据
def InitDB():
print “开始建立文件索引,请等待…”
global file_number
file_number = 0
time_start = time.clock()
create_db()
all_files(“c”)
all_files(“d”)
all_files(“e”)
all_files(“f”)
time_end = time.clock()
print “文件索引建立完毕!”
print “用时: “+str(time_end)
print “文件数: “+str(file_number)
#查找
def find_file(file_name):
find_con = sqlite3.connect(‘d:/mydatabase.db’)
find_cur = find_con.cursor()
find_cur.execute(‘SELECT * FROM FOO WHERE file_name = ?’,[file_name.decode(‘gbk’)])
find_con.commit
find_con.close
print find_cur.fetchall()
if __name__ == “__main__”:
if(os.path.exists(‘d:\mydatabase.db’) == False):
InitDB()
while(1):
find_file_name = raw_input(“输入要查找的文件名:”)
if(find_file_name == “#exit”):
break
find_file(find_file_name)
这个程序在执行初始化扫面全盘时,还是比较耗时的,主要瓶颈在sqlite的IO上,这这个Blog的时候,程序已经跑了至少5分钟了,目测扫了40%的数据…估计全盘骚下来得10多分钟。。。。。
后面有时间了优化下看看初始化的耗时情况,另外,如果用C语言实现,耗时应该更少。