文件搜索_文件搜索工具 - CSDN
精华内容
参与话题
  • 文件搜索(很实用)

    2014-05-13 22:46:46
    搜索文件名 首先介绍一下软件吧 光速搜索,有绿色版,很小巧。NTFS格式的磁盘,秒搜,搜索文件名,支持模糊搜索。(第一次打开需要创建索引,需要3、4秒) 看图: 搜索说明的文件   文件太多,可以搜索 ...

    搜索文件名

    首先介绍一下软件吧

    光速搜索,有绿色版,很小巧。NTFS格式的磁盘,秒搜,搜索文件名,支持模糊搜索。(第一次打开需要创建索引,需要3、4秒)

    看图:

    搜索说明的文件

         

    文件太多,可以搜索  

    说明.txt ,    知道后缀。

     D:\  说明.txt    知道那个盘  

    D:\*         *.txt          *.pdf        *表示统配符

    还有很多需要自己摸索一下。

    搜索文本、Word内容

    可是光速搜索只能搜文件名,介绍一下windows自带的,可以搜索 文本内部内容。但是速度不及光速搜索,很满足了

    有的默认搜索内容是关闭的,打开方法,点击搜索框


    大概记得哪个文件夹,或者哪个盘。进去之后,搜索框 *.txt office



      

    展开全文
  • 文件搜索项目

    2020-03-09 14:18:28
    文件搜索项目项目目标项目使用技术栈与平台项目背景项目功能项目演示选择文件目录根据文件名搜索根据全拼搜索根据拼音首字母搜索系统流程整体流程文件对比流程技术栈介绍SQLite介绍Pinyin4j介绍JavaFX介绍系统设计...

    项目源码

    项目源码:https://gitee.com/li_tong_jia/project.git

    项目目标

    • 巩固多线程、JDBC、集合框架等技术
    • 满足文件搜索的需求

    项目使用技术栈与平台

    • 所用技术:JavaFX、多线程、SQLite、pinyin4j
    • 平台与环境:Windows/Mac,IDEA,Maven

    项目背景

    各个操作系统下,都有提供文件搜索的功能,如windows中查找文件:

    在这里插入图片描述

    除系统自带的文件搜索功能外,也有大佬开发的很多搜索神器,比如Everything

    在这里插入图片描述

    • Everything是基于NTFS文件系统的USN Journal(Update SequenceNumber Journal),是利用操作系统记录的文件操作日志来进行搜索,特点是效率高,速度快,但是具有一定的局限性,只能用于NTFS文件系统。
    • 本项目使用实时的本地文件进行搜索,保存文件信息以便于提高搜索效率。

    项目功能

    • 指定搜索目录,显示目录中的所有文件、文件夹信息
    • 使用多线程进行文件搜索操作,文件信息保存在数据库。如果已保存有的文件信息,执行本地目录与数据库文件信息比对操作,在更新到数据库。
    • 可以根据文件名进行搜索
    • 文件名包含中文时,支持汉语拼音的搜索(全拼或是首字母匹配)

    项目演示

    选择文件目录

    扫描本地文件,保存文件信息并显示

    在这里插入图片描述

    根据文件名搜索

    在这里插入图片描述

    根据全拼搜索

    在这里插入图片描述

    根据拼音首字母搜索

    在这里插入图片描述

    系统流程

    整体流程

    在这里插入图片描述

    文件对比流程

    在这里插入图片描述

    技术栈介绍

    SQLite介绍

    • SQLite是一款轻量级的嵌入式内存数据库(嵌入在进程中,运行在内存中的数据库),使用 ANSIC 编写的,并提供了简单和易于使用的 API。
    • 一个完整的 SQLite 数据库是存储在一个单一的跨平台的磁盘文件。
    • 非常小,是轻量级的,完全配置时小于 400KiB,省略可选功能配置时小于250KiB。
    • 无需安装、配置及管理。
    • 完全兼容 ACID 事务,允许从多个进程或线程安全访问。
    • 支持多种开发语言,C, C++, PHP, Perl, Java, C#,Python, Ruby等
    • 支持 SQL92(SQL2)标准的大多数查询语言的功能。

    Pinyin4j介绍

    • 是一个Java的内库,提供对中文汉字到拼音的转换
    • 存在多音字的情况,根据一个字符可以获取多个字符串
    String[] pinyins = PinyinHelper.toHanyuPinyinStringArray('长'); 
    

    输出:
    [zhang3, chang2]

    • 可以配置输出格式,包括大小写、是否带音调(默认带)、是否使用v(如绿的拼音lv)

    JavaFX介绍

    • Java客户端UI库:JavaFX是一个强大的图形和多媒体处理工具包集合,它允许开发者来设计、创建、测试、调试和部署富客户端程序,并且和Java一样跨平台。
    • 提供了丰富的客户端组件:面板、按钮、文本框、表格等,还提供了各类事件、动画效果支持。
    • 提供了Web组件支持:HTML5的支持、CSS样式支持,JavaScript脚本支持。
    • 还提供了Scene Builder 程序,来支持拖拽式界面开发。
    • Java原有Swing、AWT客户端UI工具包,JavaFX 系统界面样式跟美观、系统架构对开发更友好、便捷

    系统设计

    sql表单 : 数据库设计

    • 需要保存的文件基本信息有:文件名称、路径、大小、上次修改时间
    • 文件名包含中文时,要满足全拼和拼音首字母的搜索,所以还需要保存全拼和拼音首字母
    • 中文汉字可能存在多音字的情况,我们这里只实现简单的,取第一个拼音即可

    工具类 : JDBC工具类设计

    • 使用SQLite,需要先指定本地数据库文件路径,如果没有则创建该文件
    • 提供获取数据库连接的方法
    • 提供释放数据库资源的方法
      数据库初始化任务
    • 读取本地写好的sql文件,再执行数据库初始化建表操作

    数据库初始化任务

    • 读取本地写好的sql文件,再执行数据库初始化建表操作

    工具类 : 拼音工具类

    • 需要提供获取文件名的全拼及拼音首字母的方法

    JavaFX界面设计

    • 界面的搭建
    • 绑定选择文件目录事件,在每次事件发生时,调用该事件方法:启动目录扫描任务,并在完成后刷新表格
    • 绑定搜索框内容改变事件,在每次事件发生时,调用该事件方法:搜索文件信息,并刷新表格

    任务型 :多线程目录扫描任务设计

    • 入口是在选择文件目录事件发生后,根据选定的目录进行扫描
    • 扫描到目录(文件夹)时,执行目录下一级子文件的信息对比、更新操作
    • 如果目录下一级子文件是文件夹,则开启新的子任务处理这个子文件夹
    • 在所有任务都完成以后,刷新表格

    业务型:本地文件、数据库文件对比及更新

    • 本地有,数据库没有,插入该文件信息
    • 数据库有,本地没有,删除数据库中该文件信息。如果该文件是文件夹,还需要删除所有在该文件夹下的文件

    功能:文件搜索

    • 根据搜索值,模糊匹配文件名,全拼或拼音首字母字段,任意匹配成功都可以获取文件信息

    开发步骤

    创建Maven项目

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>tong</groupId>
        <artifactId>ErLangShen</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <dependencies>
            <dependency>
                <groupId>com.belerweb</groupId>
                <artifactId>pinyin4j</artifactId>
                <version>2.5.1</version>
            </dependency>
            <dependency>
                <groupId>org.xerial</groupId>
                <artifactId>sqlite-jdbc</artifactId>
                <version>3.28.0</version>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.1</version>
                    <configuration>
                        <source>1.8</source>
                        <target>1.8</target>
                        <encoding>UTF-8</encoding>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-jar-plugin</artifactId>
                    <version>3.1.0</version>
                    <configuration>
                        <archive>
                            <manifest>
                                <mainClass>Main</mainClass> <!-- 指定入口类 -->
                                <addClasspath>true</addClasspath> <!-- 在jar的MF文件中
    生成classpath属性 -->
                                <classpathPrefix>lib/</classpathPrefix> <!--
    classpath前缀,即依赖jar包的路径 -->
                            </manifest>
                        </archive>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-dependency-plugin</artifactId>
                    <version>3.1.1</version>
                    <executions>
                        <execution>
                            <id>copy</id>
                            <phase>package</phase>
                            <goals>
                                <goal>copy-dependencies</goal>
                            </goals>
                            <configuration>
                                <!-- 指定依赖包的输出路径,需与上方的classpathPrefix保持一
                                致 -->
                                <outputDirectory>${project.build.directory}/lib</outputDirectory>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    
    </project>

    设计数据库表

    drop table if exists file_meta;
    
    CREATE TABLE IF NOT EXISTS file_meta (
        name VARCHAR(50) NOT NULL,
        path VARCHAR(1000) NOT NULL,
        is_directory boolean not null ,
        size BIGINT NOT NULL,
        last_modified TIMESTAMP NOT NULL,
        pinyin VARCHAR(50),
        pinyin_first VARCHAR(50)
    );

    设计数据库工具类,及表初始化操作

    • URL格式为:jdbc:sqlite://数据库本地文件路径,没有用户名密码。使用URL创建DataSource对象后,会以该路径文件作为数据库,没有则创建该文件。
    private static String getUrl(){
        //classes路径
        URL classesURL = DBUtil.class.getClassLoader().getResource("./"); //classes路径
        //target路径
        String dir = new File(classesURL.getPath()).getParent();
        //ErLangShen.db路径 jdbc:sqlite://D:\java%20code\%e9%a1%b9%e7%9b%ae\ErLangShen\target\ErLangShen.db
        String url  = "jdbc:sqlite://" + dir + File.separator + "ErLangShen.db";
        return url;
    }
    • 设计单例模式获取DataSource连接池对象。及通过DataSource获取数据库连接的方法。
    private static volatile DataSource DATA_SOURCE;
    
    /**
     *提供获取数据库连接词的功能
     * 使用单例模式(多线程安全)
     * 多线程安全版本的单例模式:
     * 1.为什么在最外层判断是否为null?
     * 2.synchronized加锁以后,为什么还要判断是否为null
     * 3.为什么Datasource类变量要使用volatile关键字修饰
     * 多线程操作:原子性,可见性(从主内存拷贝到工作内存),有序性
     * synchronized保证前三个特性,volatile保证可见性,有序性
     * @return
     */
    private static DataSource getDataSource(){
        if (DATA_SOURCE == null){ //提高效率
            //保证只有一个不为空的DATA_SOURCE   单例
                synchronized (DBUtil.class){
                if (DATA_SOURCE == null){
                    SQLiteConfig config = new SQLiteConfig();
                    config.setDateStringFormat(Util.DATA_PATTERN);
                    DATA_SOURCE = new SQLiteDataSource();
                    ((SQLiteDataSource)DATA_SOURCE).setUrl(getUrl());
                }
            }
        }
        return DATA_SOURCE;
    }
    • 设计释放资源的方法:关闭连接Conncetion、关闭数据库操作对象Statement、关闭结果集对象ResultSet。
    public static void close(Connection connection, Statement statement) {
        close(connection,statement,null);
    }
    
    public static void close(Connection connection, Statement statement, ResultSet resultSet)  {
        try {
            if (connection != null) {
                connection.close();
            }
            if (statement != null) {
                statement.close();
            }
            if (resultSet != null){
                resultSet.close();
            }
        }catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException("释放资源失败",e);
        }
    
    }
    • 建立连接
    public static Connection getConnection() throws SQLException {
        return getDataSource().getConnection();
    
    }

    初始化数据库

    /**
     * 读取sql文件
     *
     */
    public static String[] readSql() {
        try {
            //通过ClassLoader获取流
            InputStream in = DBInit.class.getClassLoader().getResourceAsStream("init.sql");
            //字节流转换为字符流
            BufferedReader br = new BufferedReader(new InputStreamReader(in,"UTF-8"));
            StringBuilder sb = new StringBuilder();
            String line ;
            while((line = br.readLine()) != null){
                if (line.contains("--")){
                    line = line.substring(0,line.indexOf("--"));
                }
                sb.append(line);
            }
            String[] sqls = sb.toString().split(";");
            return sqls;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("读取错误");
        }
    }
    
    public static void init() {
        //数据库jdbc操作
        //1.建立数据库连接connection
        Connection connection = null;
        Statement statement = null;
        try {
            //1.建立数据库连接connection
            connection = DBUtil.getConnection();
            //2.创建sql语句执行对象Statement
            String[] sqls = readSql();
            //2.创建sql语句执行对象Statement
            statement = connection.createStatement();
            for (String sql:sqls
                 ) {
                //3.执行sql
                statement.executeUpdate(sql);
            }
            //4.如果是查询操作,获取结果集ResultSet,处理结果集
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException("初始话数据库表操作失败",e);
        }finally {
            //5.释放资源
            DBUtil.close(connection,statement);
        }
    
    }
    
    public static void main(String[] args) {
        System.out.println(Arrays.toString(readSql()));
    }

    设计汉语拼音工具

    • 使用第三方库提供的汉字到拼音的转换,一个汉字转换出来可能有多个拼音。配置汉字的字符范围,及拼音的输出格式(小写、不带音调、包含V字符)
    /**
     * 中文字符格式
     */
    private static final String CHINESE_PATTERN = "[\\u4E00-\\u9FA5]";
    
    /**
     * 汉语拼音格式化类
     */
    private static final HanyuPinyinOutputFormat FORMAT = new HanyuPinyinOutputFormat();
    
    static {
        FORMAT.setCaseType(HanyuPinyinCaseType.LOWERCASE); //小写拼音
        FORMAT.setToneType(HanyuPinyinToneType.WITHOUT_TONE);  //不带声调
        FORMAT.setVCharType(HanyuPinyinVCharType.WITH_V);  //带v
    
    }
    
    /**
     * 字符串中是否包含中文
     * @param name
     * @return
     */
    public static boolean containsChinese(String name) {
        //正则表达式
        return name.matches(".*" + CHINESE_PATTERN + ".*");
    }
    • API有提供单个字符的拼音转换:
    String[] temp = PinyinHelper.toHanyuPinyinStringArray(c,
    PINYIN_OUTPUT_FORMAT); 
    • 多个字符组成的文件名,需要按照每个字符返回的字符串数组进行排列组合,我们只简单实现,每个字符取第一个返回的字符串作为拼音。拼音分全拼,和汉字首字母拼接的两种方式
    /**
     * 通过文件名获取全拼+拼音首字母
     * 中华人民共和国--->zhongghuarenmingongheguo/zhrmghg(不考虑多音字)
     * @param name 文件名
     * @return    全拼+拼音首字母  数组
     */
    public static String[] get(String name){
        String[] result = new String[2];
        StringBuilder all = new StringBuilder();//全拼
        StringBuilder first = new StringBuilder();//首字母
    
        for (char c:name.toCharArray()
             ) {
            try{
                String[] pinyins = PinyinHelper.toHanyuPinyinStringArray(c,FORMAT);//多音字
                if(pinyins == null || pinyins.length == 0){
                    all.append(c);
                    first.append(c);
                }else {
                    all.append(pinyins[0]);
                    first.append(pinyins[0].charAt(0));
                }
            }catch (BadHanyuPinyinOutputFormatCombination badHanyuPinyinOutputFormatCombination) {
                all.append(c);
                first.append(c);
            }
        }
        result[0] = all.toString();
        result[1] = first.toString();
        return result;
    }
    • 如果考虑多音字的话
    /**
     * 多音字版获取名称
     * @param name 文件名
     * @param fullSpell true为全拼,false为首字母
     * @return 文件名多音字数组
     */
    public static String[][] get(String name,boolean fullSpell){
        char[] chars = name.toCharArray();
        String[][] result = new String[chars.length][];
        for (int i = 0; i < chars.length; i++) {
            try{
                //去除音调后,会有重复,"只":[zhi,zhi...]---------quchong
                String[] pinyins = PinyinHelper.toHanyuPinyinStringArray(chars[i],FORMAT);//多音字
    
                if(pinyins == null || pinyins.length == 0){
                   result[i] = new String[]{String.valueOf(chars[i])};
                }else{
                    result[i] = unique(pinyins,fullSpell);
                }
            }catch (BadHanyuPinyinOutputFormatCombination badHanyuPinyinOutputFormatCombination) {
                result[i] = new String[]{String.valueOf(chars[i])};
            }
        }
        return result;
    }
    
    /**
     * 数组去重操作
     * @param array
     * @param fullSpell
     * @return
     */
    public static String[] unique(String[] array,boolean fullSpell){
        Set<String> set = new HashSet<>();
        for (String s:array
             ) {
            if(fullSpell){
                set.add(s);
            }else {
                set.add(String.valueOf(s.charAt(0)));
            }
        }
        return set.toArray(new String[set.size()]);
    }
    
    /**
     * 每个中文字符返回的是字符串数组,每两个字符串数组合并为一个字符串数组,之后以此类推
     * @param pinyinArray 文件名多音字数组
     * @return 返回文件名的排列组合
     */
    public static String[] compose(String[][] pinyinArray){
        if (pinyinArray == null || pinyinArray.length == 0){
            return null;
        }else if (pinyinArray.length == 1){
            return pinyinArray[0];
        }else {
            String[] result = pinyinArray[0];
            for (int i = 1; i < pinyinArray.length; i++) {
                result = compose(result,pinyinArray[i]);
            }
            return result;
        }
    }
    
    /**
     * 拼音数组两两组合
     * @param pinyin1
     * @param pinyin2
     * @return 返回组合
     */
    public static String[] compose(String[] pinyin1,String[] pinyin2){
        String[] result = new String[pinyin1.length*pinyin2.length];
        int k = 0;
        for (int i = 0; i < pinyin1.length; i++) {
            for (int j = 0; j < pinyin2.length; j++) {
                result[k] = pinyin1[i] + pinyin2[j];
                k++;
            }
        }
        return result;
    }

    设计界面及文件信息搜索

    • Main.java
    public class Main extends Application {
    
        @Override
        public void start(Stage primaryStage) throws Exception{
            Parent root = FXMLLoader.load(getClass().getClassLoader().getResource("app.fxml"));
            primaryStage.setTitle("ErLangShen");
            primaryStage.setScene(new Scene(root, 1000, 800));
            primaryStage.show();
        }
        public static void main(String[] args) {
            launch(args);
        }
    }
    • app.fxml
    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.geometry.*?>
    <?import javafx.scene.layout.*?>
    <?import javafx.scene.control.*?>
    <?import javafx.scene.control.cell.*?>
    
    <GridPane fx:id="rootPane" alignment="center" hgap="10" vgap="10" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="app.Controller">
        <children>
    
            <Button onMouseClicked="#choose" prefWidth="90" text="选择目录" GridPane.columnIndex="0" GridPane.rowIndex="0" />
            <Label fx:id="srcDirectory">
                <GridPane.margin>
                    <Insets left="100.0" />
                </GridPane.margin>
            </Label>
            <TextField fx:id="searchField" prefWidth="900" GridPane.columnIndex="0" GridPane.rowIndex="1" />
    
            <TableView fx:id="fileTable" prefHeight="700" prefWidth="900" GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.rowIndex="2">
                <columns>
                    <TableColumn fx:id="nameColumn" prefWidth="220" text="名称">
                        <cellValueFactory>
                            <PropertyValueFactory property="name" />
                        </cellValueFactory>
                    </TableColumn>
                    <TableColumn prefWidth="400" text="路径">
                        <cellValueFactory>
                            <PropertyValueFactory property="path" />
                        </cellValueFactory>
                    </TableColumn>
                    <TableColumn fx:id="sizeColumn" prefWidth="120" text="大小">
                        <cellValueFactory>
                            <PropertyValueFactory property="sizeText" />
                        </cellValueFactory>
                    </TableColumn>
                    <TableColumn fx:id="lastModifiedColumn" prefWidth="160" text="修改时间">
                        <cellValueFactory>
                            <PropertyValueFactory property="lastModifiedText" />
                        </cellValueFactory>
                    </TableColumn>
                </columns>
            </TableView>
        </children>
    </GridPane>
    
    • Controller
    public class Controller implements Initializable {
    
        @FXML
        private GridPane rootPane;
    
        @FXML
        private TextField searchField;
    
        @FXML
        private TableView<FileMeta> fileTable;
    
        @FXML
        private Label srcDirectory;//标签
    
        private Thread task;
        public void initialize(URL location, ResourceBundle resources) {
            //界面初始化时,需要初始化数据库及表
            DBInit.init();
            // 添加搜索框监听器,内容改变时执行监听事件
            searchField.textProperty().addListener(new ChangeListener<String>() {
    
                public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                    freshTable();
                }
            });
        }
    
        /**
         * 点击选择目录
         * @param event
         */
        public void choose(Event event) {
            // 选择文件目录
            DirectoryChooser directoryChooser=new DirectoryChooser();
            Window window = rootPane.getScene().getWindow();
            File file = directoryChooser.showDialog(window);
            if(file == null)
                return;
            // 获取选择的目录路径,并显示
            String path = file.getPath();
            srcDirectory.setText(path);
            //选择目录就需要执行目录的扫描任务:该目录下的目录及子目录下的文件夹
    
            if(task != null){
                task.interrupt();//中断
            }
                task = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println("执行文件扫描任务");
                        ScanCallback callback = new FileSave();
                        FileScanner scan = new FileScanner(callback);
                        scan.scan(path);//多线程扫描.提高效率
                        //等待扫描完毕;
                        try {
                            scan.waitFinish();
                            System.out.println("所有任务执行完毕,刷新表格");
                            //刷新表格:将扫描的子文件和子文件夹都展示在表格
                            freshTable();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
    
                        }
                    }
                });
                task.start();
    
        }
    
    
    
        // 刷新表格数据
        private void freshTable(){
            ObservableList<FileMeta> metas = fileTable.getItems();
            metas.clear();
            String dir = srcDirectory.getText();
            if (dir != null && dir.trim().length() != 0){
                String content = searchField.getText();
                //提供数据库的查询方法
                List<FileMeta> fileMetas = FileSearch.search(dir,content);
                metas.addAll(fileMetas);
            }
        }
    }

    设计多线程扫描任务及文件信息保存

    • 多线程执行大量任务,使用线程池来提高执行效率
    private ExecutorService pool = Executors.newFixedThreadPool(4);
    • 为便于在线程中执行的任务有较好的扩展性,可以考虑使用接口回调的方式实现。传入时设定为文件信息保存的任务。
    public FileScanner(ScanCallback callback) {
        this.callback = callback;
    }
    • 在线程执行时,待执行任务数+1, 执行完后,待执行任务数-1,开启子任务时,每个子任务都执行任务数+1操作,这样在最后可以判断出是否所有线程执行完毕。
    private volatile AtomicInteger count = new AtomicInteger();
    /**
     * 扫描文件目录
     * 开始不知道多少子文件夹
     * @param path
     */
    public void scan(String path) {
        count.incrementAndGet();//根目录扫描任务,计数器++i
        doScan(new File(path));
    }
    
    private void doScan(File dir){
        callback.callback(dir);
        pool.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    File[] children = dir.listFiles();
                    if (children != null) {
                        for (File file : children
                        ) {
                            if (file.isDirectory()) {//如果是文件夹,递归
                               // System.out.println("文件夹" + file.getPath());
                                count.incrementAndGet();//++i
                                doScan(file);
                            }
                        }
                    }
                }finally {
                    int c = count.decrementAndGet();
                    if (c == 0){
                        synchronized (lock){
                            lock.notify();
                            System.out.println("********************************************");
                        }
                    }
                }
            }
        });
    }

    本地文件、数据库文件对比及更新

    • 本地有,数据库没有,插入该文件信息
    /**
     * 文件保存在数据库
     * @param file
     */
    private void save(FileMeta file){
        Connection connection = null;
        PreparedStatement statement = null;
        try {
            connection = DBUtil.getConnection();
            String sql = "insert into file_meta" +
                    "(name, path, is_directory, size, last_modified, pinyin, pinyin_first)" +
                    " values (?,?,?,?,?,?,?)";
            statement = connection.prepareStatement(sql);
            statement.setString(1,file.getName());
            statement.setString(2,file.getPath());
            statement.setBoolean(3,file.getDir());
            statement.setLong(4,file.getSize());
            statement.setTimestamp(5,new Timestamp(file.getLastModified().getTime()));
            statement.setString(6,file.getPinyin());
            statement.setString(7,file.getPinyinFirst());
            System.out.printf("insert name=%s, path=%s\n", file.getName(), file.getPath());
            statement.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException("文件保存失败" + e);
        }finally {
            DBUtil.close(connection,statement);
        }
    }
    • 数据库有,本地没有,删除数据库中该文件信息。如果该文件是文件夹,还需要删除所有在该文件夹下的文件
    private void delete(FileMeta meta) {
        Connection connection = null;
        PreparedStatement ps = null;
        try {
            connection  = DBUtil.getConnection();
            String sql = "delete from file_meta where" +
                    " (name = ? and path = ? and is_directory = ?)" ;
            if (meta.getDir()){
                sql += " or path=?" +
                        " or path like ?";
            }
            ps = connection.prepareStatement(sql);
            ps.setString(1,meta.getName());
            ps.setString(2,meta.getPath());
            ps.setBoolean(3,meta.getDir());
            if (meta.getDir()){
                ps.setString(4,meta.getPath() + File.separator + meta.getName());
                ps.setString(5,meta.getPath() + File.separator + meta.getName() + File.separator +"%");
            }
            System.out.printf("删除文件信息,dir=%s\n",
                    meta.getPath()+File.separator+meta.getName());
            ps.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException("删除文件信息出错,检查delete语句", e);
        }finally {
            DBUtil.close(connection,ps);
        }
    }

    项目总结

    • 项目优点:使用多线程来进行文件遍历,提高了效率。
    • 项目缺点:中文汉字多音字没有进行排列组合,只能支持多音字拼音的一种组合搜索。
    • 项目扩展:我们还能将该项目写的更完善,可以往以下几个发展方向走:
      1. 多音字支持
      2. 将项目打包成exe安装文件

    项目参考资料

    • SQLite Home Page
    • Pinyin4j、http://pinyin4j.sourceforge.net/
    • JavaFX官网、FX China、JavaFX 教程
    展开全文
  • Java实现文件搜索

    千次阅读 2018-09-03 20:00:04
    package com.msmk.cloud; import java.io.File; import java.io.FileFilter; import java.util.ArrayList; import java.util.List; public class searchFileTest { public static List&... searchFil...

    转自:https://baike.xsoftlab.net/view/46.html#1

    package com.msmk.cloud;
    
    import java.io.File;
    import java.io.FileFilter;
    import java.util.ArrayList;
    import java.util.List;
    
    public class searchFileTest {
    
        public static List<File> searchFiles(File folder, final String keyword) {
            List<File> result = new ArrayList<File>();
            if (folder.isFile())
                result.add(folder);
    
            File[] subFolders = folder.listFiles(new FileFilter() {
                @Override
                public boolean accept(File file) {
                    if (file.isDirectory()) {
                        return true;
                    }
                    if (file.getName().toLowerCase().contains(keyword)) {
                        return true;
                    }
                    return false;
                }
            });
    
            if (subFolders != null) {
                for (File file : subFolders) {
                    if (file.isFile()) {
                        // 如果是文件则将文件添加到结果列表中
                        result.add(file);
                    } else {
                        // 如果是文件夹,则递归调用本方法,然后把所有的文件加到结果列表中
                        result.addAll(searchFiles(file, keyword));
                    }
                }
            }
    
            return result;
        }
    
        public static void main(String[] args) {
            List<File> files = searchFiles(new File("/home/xyh/ll3dupload/model/decompress/"), "00999.jpg");
            System.out.println("共找到:" + files.size() + "个文件");
            for (File file : files) {
                System.out.println(file.getAbsolutePath());
            }
        }
    }
    展开全文
  • 文件搜索(File)

    千次阅读 2020-08-04 00:18:17
    1.java.io.File 类是文件和目录路径名的抽象表示,主要用于文件和目录的创建、查找和删除等操作 2.构造方法: public File(String pathname) :通过文件路径名创建 File实例 public File(String parent, String ...

    一、File类

    1.java.io.File 类是文件和目录路径名的抽象表示,主要用于文件和目录的创建、查找和删除等操作
    2.构造方法:

    • public File(String pathname) :通过文件路径名创建 File实例
    • public File(String parent, String child) :通过父路径名字符串子路径名字符串创建 File实例
    • public File(File parent, String child) :通过父级File对象子路径名字符串创建File实例
    		//文件路径名
            String pathname = "E:\\aaa\\aa";
            File file = new File(pathname);
    
            //通过父路径和子路径字符串
            String parent = "E:\\aaa\\aa";
            String child = "b.txt";
            File file2 = new File(parent,child);
    
            //通过父级File对象和子路径字符串
            File parentDir = new File("E:\\aaa\\aa");
            String child2 = "b.txt";
            File file3 = new File(parentDir,child2);
    

    3.常用方法:
    (1)获取功能的方法:

    • public String getAbsolutePath() :返回此File的绝对路径名字符串

    • public String getPath() :将此File转换为路径名字符串。

    • public String getName() :返回由此File表示的文件或目录的名称

    • public long length() :返回由此File表示的文件的长度

     		File f = new File("\\aaa\\aa\\b.txt");
            System.out.println("文件绝对路径:" + f.getAbsolutePath()); //文件绝对路径:D:\aaa\aa\b.txt
            System.out.println("文件构造路径:" + f.getPath()); //文件构造路径:\aaa\aa\b.txt
            System.out.println("文件名称:" + f.getName()); //文件名称:b.txt
            System.out.println("文件长度:" + f.length() + "字节"); //文件长度:0字节
    

    (2)绝对路径和相对路径

    • 绝对路径:从盘符开始的路径,这是一个完整的路径
    • 相对路径:相对于项目目录的路径,这是一个便捷的路径,开发中经常使用
    		//E:\aaa\aa下的b.txt文件
            File f = new File("E:\\aaa\\aa\\b.txt");
            System.out.println(f.getAbsolutePath()); //E:\aaa\aa\b.txt
    
            //项目下的b.txt
            File f2 = new File("b.txt");
            System.out.println(f2.getAbsolutePath()); //D:\IdeaProjects\feisi\b.txt
    

    (3)判断功能的方法:

    • public boolean exists() :此File表示的文件或目录是否实际存在
    • public boolean isDirectory() :此File表示的是否为目录
    • public boolean isFile() :此File表示的是否为文件
    		File f = new File("E:\\aaa\\aa\\b.txt");
            File f2 = new File("E:\\aaa\\aa");
    
            //判断是否存在
            System.out.println(f.exists()); //true
            System.out.println(f2.exists()); //true
    
            //判断是文件还是目录
            System.out.println(f.isFile()); //true
            System.out.println(f.isDirectory()); //false
    

    (4)创建删除功能的方法

    • public boolean createNewFile() :当且仅当具有该名称的文件尚不存在时,创建一个新的空文件
    • public boolean delete() :删除由此File表示的文件或目录
    • public boolean mkdir() :创建由此File表示的目录
    • public boolean mkdirs() :创建由此File表示的目录,包括任何必需但不存在的父目录
    		//文件的创建
            File f = new File("a.txt");
            System.out.println(f.createNewFile()); //true
    
            //目录的创建
            File f2 = new File("Dir");
            System.out.println(f2.mkdir()); //true
    
            //创建多级目录
            File f3 = new File("Dir\\dir");
            System.out.println(f3.mkdirs()); //true
    
            //文件的删除(如果此File目录,则目录必须为空才能删除,文件则直接删除)
            System.out.println(f.delete()); //true
    

    (5)目录的遍历

    • public String[] list() :返回一个String数组,表示该File目录中的所有子文件或目录
    • public File[] listFiles() :返回一个File数组,表示该File目录中的所有的子文件或目录
    		File dir = new File("E:\\aaa");
    
            //获取当前目录下的文件以及文件夹的名称
            String[] names = dir.list();
            for (String name : names) {
                System.out.println(name); //a.txt aa
            }
    
            //获取当前目录下的文件以及文件夹对象
            File[] files = dir.listFiles();
            for (File file : files) {
                System.out.println(file); //E:\aaa\a.txt E:\aaa\aa
            }
    

    4.递归打印多级目录
    遍历之前,我们不知道有多少级目录,所以我们要使用递归实现

        public static void main(String[] args) {
    
            File dir = new File("E:\\aaa");
            printDir(dir);
    //        打印结果
    //        E:\aaa\a.txt
    //        E:\aaa\aa
    //        E:\aaa\aa\b.txt
    
        }
    
        public static void printDir(File dir) {
    
            File[] files = dir.listFiles();
            for (File file : files) {
    
                if(file.isFile()){
                    System.out.println(file.getAbsolutePath());
                } else {
                    System.out.println(file.getAbsolutePath());
                    printDir(file);
                }
            }
        }
    
    

    二、典型案例

    搜索D:\aaa 目录中的.java 文件
    分析

    1. 目录搜索,无法判断多少级目录,所以使用递归,遍历所有目录。
    2. 遍历目录时,获取的子文件,通过文件名称,判断是否符合条件。

    代码实现

    	public static void main(String[] args) {
            // 创建File对象
            File dir  = new File("D:\\aaa");
          	// 调用打印目录方法
            printDir(dir);
        }
    
        public static void printDir(File dir) {
          	// 获取子文件和目录
            File[] files = dir.listFiles();
          	
          	// 循环打印
            for (File file : files) {
                if (file.isFile()) {
                  	// 是文件,判断文件名并输出文件绝对路径
                    if (file.getName().endsWith(".java")) {
                        System.out.println("文件名:" + file.getAbsolutePath());
                    }
                } else {
                    // 是目录,继续遍历,形成递归
                    printDir(file);
                }
            }
        }
    
    展开全文
  •   介绍三款文件内容快速搜索工具,分别为 Everything、Listary 和 DocFetcher,...Listary 不仅可以对文件进行快速搜索,而且启动速度快,还可以搜索软件应用从而快速打开软件,并且可与文件资源管理器配合使用...
  • 关于文件搜索的软件

    千次阅读 2018-04-30 17:11:18
    关于搜索,我说的是本地搜索,也就是自己电脑上,有两类软件可以好好利用:文件名搜索文件搜索。 文件名搜索 关于文件名搜索有两个著名的软件,分别是Everything和Listary(windows效率软件不完全指南 里面...
  • Linux下文件搜索、查找、查看命令

    万次阅读 多人点赞 2018-10-12 15:03:45
    Linux下文件搜索、查找、查看命令 1、最强大的搜索命令:find 一、根据 文件或目录名称 搜索 二、根据 文件大小 搜索 三、根据 所有者和所属组 搜索 四、根据 时间属性 搜索 五、根据 文件类型或i节点 搜索 六、组合...
  • idea 快速查找各种文件的方法

    万次阅读 多人点赞 2018-09-30 09:14:17
    双击shift会弹出一个搜索框,输入关键字搜索即可 当然还可以cmd+shift+f 不过个人觉得第一种方式更快捷。 以上from 同事 ygj
  • mac通过命令行搜索文件

    万次阅读 2015-05-16 17:27:01
    通过Find命令搜索文件find命令非常高效,并且使用简单。find命令来自unix,OS X和Linux系统同样支持该命令。find最基本的操作就是:find 文件路径 参数 复制代码 比如你可以通过以下命令在用户文件夹中搜索名字中...
  • 组织—文件夹选项—常规—导航窗格—自动扩展到当前文件夹 文件夹选项—搜索搜索内容—始终搜索文件名和内容,同时选“搜索方式”—包括子文件夹
  • webstorm中怎么搜索文件

    万次阅读 2018-06-14 20:09:26
    Ctrl+N 文件搜索Ctrl+SHIFT+R 关键字搜索
  • Linux常用命令--文件搜索

    万次阅读 2019-03-27 15:47:08
    目录 find locate which whereis ...命令用途:在指定目录下搜索文件或目录。...命令语法:find [搜索范围] [-选项] [匹配条件] ...-name:根据文件名...// 搜索/etc目录下文件名为init的文件或目录 find /etc -name...
  • Sublime Text 如何查找文件

    万次阅读 2018-05-25 14:58:32
    ctrl + p, 然后输入文件名(可模糊搜索)
  • 出自:https://blog.csdn.net/inowcome/article/details/6699227在...我们可以通过通配符或正则表达式来设定查寻条件,下面是操作示例: ctrl+h 打开搜索界面搜索结果:通过文件可能包含的文本内容进行搜索使用File...
  • 有四种方法: find 文件目录 -name ‘*.*' -exec grep 'xxx' {} + -n 或是 find 文件目录 -name '*.*' | xargs grep 'xxx' -n 或是 grep 'XXX' 文件目录 -Rn 或是 grep 'XXX' `find 文件目录 -name '*.*'`
  • 组织------文件夹和搜索选项--------始终搜索文件和内容
  • 在ubuntu中搜索文件或文件夹的方法

    万次阅读 多人点赞 2017-09-17 00:46:59
    用于程序名的搜索搜索结果只限于二进制文件(参数-b)、man说明文件(参数-m)和源代码文件(参数-s),如果省略参数,则返回所有信息。  特点:快速,但是是模糊查找,例如 找 #whereis mysql 它会把mysql,...
  • Everything是速度最快的文件搜索软件。其速度之快令人震惊,百G硬盘几十万个文件,可以在几秒钟之内完成索引;文件名搜索瞬间呈现结果。它小巧免费,支持中文,支持正则表达式,可以通过HTTP或FTP分享搜索结果。如果...
  • 包括子目录.grep -r "待查找内容" ./
  • webstorm 按照文件名查找文件 快捷键

    万次阅读 2016-04-17 15:29:36
    commond+shift+O 或者点击 navigate–>file 参考文档:http://stackoverflow.com/questions/18372961/how-to-search-a-file-in-phpstorm
1 2 3 4 5 ... 20
收藏数 1,320,565
精华内容 528,226
关键字:

文件搜索