My_Searcher项目说明

My_Searcher项目说明


项目源码

请参考


项目的背景

​ 在大多数操作系统中,都有着文件搜索的功能,这项功能对于那些经常忘记重要文件存放路径的“粗心鬼”来说,真的是工作和生活中必不可少的功能。

​ 在 Windows10 中,桌面底部状态栏的左侧就有着个人助理 Cortana,小娜就具有我上述的搜索功能,而且我有时也会在这里搜索一些小工具,是真的非常方便。另外,在 Windows10 的文件系统中,每一个窗口的右上角也具有一个小的搜索框,可以在当前路径下搜索需要找的文件。

​ 当然民间也有一些大神们不满于微软官方的搜索功能,于是自己动手,丰衣足食,大神们开发了很多功能强大的搜索神器,例如:Everything

​ Everything是基于NTFS文件系统的USN Journal(Update SequenceNumber Journal),是利用操作系统记录的文件操作日志来进行搜索,特点是效率高,速度快,但是具有一定的局限性,只能用于
NTFS文件系统。

​ 于是我模仿着这款搜索神器也做了一个“低配版”的搜索器。


项目的核心功能

​ 作为一款搜索器,那最基本就要能在本地中找到与目标文件名相匹配的文件,但是大多数人都不喜欢输入太精确的文件信息,因为大多数人们也许只能记得目标文件名中某些关键词,所以要解决这个问题,就得进行”模糊匹配“,将本地的文件信息保存进 SQLite 数据库,然后和用户输入的目标文件的信息进行匹配,实现文件名搜索拼音全拼搜索拼音首字母搜索。为了实现这个多功能搜索,我选择引入 pinyin4j 的 Java 类库,可以将用户输入的文件信息转换成包含全拼、首字母等的字符数组,方便后端进行后续功能的实现。


项目的开发环境

  • Windows10
  • IntelliJ IDEA
  • Maven

项目的主要流程

整体流程:

My_Searcher项目说明

文件对比流程:

My_Searcher项目说明


项目的模块组成

文件扫描任务


  • 为了提高文件扫描的效率,我引入了多线程功能。在目标路径下扫描,若遇到子文件夹便创建新线程进入子文件夹扫描子文件夹下的文件信息,以此递归来实现高效的文件扫描任务。
  • 有时候我们会遇到这种情况:第一次选择了一个错误的扫描路径,第二次才选择到争取的扫描路径。大多数人当然不愿意再等待程序扫描完第一次错误的路径后,再开始第二次正确路径的扫描。因此,我将这种情况发生时,会让程序将第一次扫描任务的线程全部阻塞掉,后来进入的线程也拒绝掉,等全部线程都停止后再开始第二次的扫描。这样就大大缩短了等第一次扫描停下来的时间,提高了扫描的效率。

文件信息存储


  • 为了达到轻量级的目的,我选择了 SQLite 作为文件信息存储的数据库。
  • 当文件扫描任务完成时,接口回调机制会提醒文件信息存储任务开始,将扫描到的文件信息按照我定义的标准格式存储进 SQLite 数据库中。此时会遇到一个主要的问题,就是本地信息和数据库中的信息不匹配,这时候就要将数据库中的文件信息与本地进行同步。主要分为以下两种情况:
    • 本地有,数据库没有,这种情况便在数据库中新增此条文件信息。
    • 数据库有,本地没有,这种情况便将数据库中的此条文件信息删除(若该条文件信息是文件夹,则删除该文件夹下所有的文件信息)。

文件信息搜索


  • 通过引入 pinyin4j 的类库,我可以将用户输入的目标文件的信息转换成汉语拼音全拼及首字母的字符数组,再到已经存放了本地文件信息的 SQLite 数据库中通过 JDBC 操作来搜索目标文件信息。

文件信息展示


  • 通过 JavaFX 创建用户界面,并将文件信息罗列在前端窗口上。
  • 当目标扫描路径改变时,清空界面列表,并重新获取新扫描路径的文件信息。

​ 另外,我再结合我的代码详细讲解一下一些部分功能的具体实现,首先将项目的模块组成以树状图的方式罗列出来,然后我再介绍各个模块的功能。

  • app 包
    • Controller 类
    • FileMeta 类
  • task 包
    • DBInit 类
    • FileSave 类
    • FileScanner 类
    • FileSearch 类
    • ScanCallBack 接口
  • util 包
    • DBUtil 类
    • PinyinUtil 类
    • Util 类
  • Main 类(总入口):调用 JavaFX 创建用户界面以及项目主入口。

  1. 在 app 包下
    • Controller 类:
      1. 提供前端用户界面的实现。
      2. 提供选择文件目录的功能。
      3. 提供用户界面列表的刷新功能。
    • FileMeta 类:
      1. 创建一个类用来存储扫描文件的信息,属性皆是数据库中的字段。
      2. 提供一个构造方法和判断是否是目录的方法。
  2. 在 task 包下
    • DBInit 类:
      • 提供两个方法,分别为 readSQL() 和 Init()。readSQL() 通过类加载器获取流,得到数据库初始化的 sql 语句,并送到 Init() 方法的Statement 中,完成数据库的初始化工作。
    • FileScanner 类:
      1. 创建线程池,使用多个线程在进行本地文件的递归遍历,其中从根路径开始,每当遇到子文件为目录时,便创建新的线程去遍历子目录。
      2. 采用接口回调机制,当 FileScanner 类完成本地文件扫描任务后,通知 FileSave 类将扫描到的文件信息保存进 SQLite 数据库。
      3. 最后提供关闭线程池的功能。应用场景为:第一步:选择了一个较大的目录,扫描开始执行。第二步:又选择了一个较小的目录。此时我们希望能够将第一次选择的大目录的扫描任务终止掉,进而让全部计算资源进行新的目录的扫描任务,所以采用 pool.shutdownNow() 方法,将第一次的扫描线程全部阻塞,并且拒绝掉后进来的线程,停止后进行第二个小的目录的遍历扫描。
    • FileSave 类:
      1. 主要提供对数据库文件信息的增、删、改、查功能。作为 FileScanner 类的上级,当下级完成扫描任务后,得到扫描完成的通知,然后将下级扫描的文件信息结果进行保存到数据库,并且获取到子文件和子文件夹的信息,若查询到子文件和子文件夹的信息和数据库里存储的信息不匹配,分为两种情况:若数据库有,但本地没有,则将数据库里的信息删除;若本地有,但数据库没有,则将本地的信息添加进数据库。
      2. 增删改查皆是基于 JDBC 的操作。
    • FileSearch 类:
      • 提供在数据库中对目标扫描路径下的子文件及子目录的查找功能。
    • ScanCallBack 接口:
      • 由 FileSave 类实现,简单的提供一个 callBack() 方法,当 FileScanner 类完成扫描后进行反馈。
  3. 在 util 包下
    • DBUtil 类:
      1. 提供了使用单例模式获取数据库连接池的功能。
      2. 获取数据库 URL 并得到数据库连接。
      3. 提供关闭数据库功能。
    • PinyinUtil 类:
      1. 提供设置中文字符格式。
      2. 提供将汉语拼音格式化为统一格式。
      3. 提供通过文件名获取目标文件全拼及拼音首字母的功能。
    • Util 类:
      1. 提供设置日期时间格式。
      2. 提供将日期解析为中文描述。
      3. 提供转换文件大小为中文描述的功能。
  4. Main 类:调用 JavaFX 创建用户界面以及项目主入口。

项目的核心技术

  1. 使用 JavaFX 制作前端用户界面。
  2. 使用多线程高效地完成本地文件的遍历扫描任务。
  3. 使用轻量级数据库 SQLite 完成本地文件信息的存储任务。
  4. 使用 pinyin4j 类库完成本地文件信息的中文汉字到汉语拼音的转换。

项目的效果

运行后的界面:

My_Searcher项目说明

选择目录后:

My_Searcher项目说明

效率:

经过实际测试,扫描完一个 32.4GB 的文件夹大约用时半分钟。