java文本搜索工具

通过关键词检索目录下的所有日志文件,然后返回搜索的内容,这个工具用于定位日志特别有用;搜索服务的类通过多线程,每一个线程搜索一个文件,效率很高,上百个文件基本上都是在几秒内完成。

搜索服务的源码

package system.service;

import system.service.base.BaseService;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

public class TextFindService extends BaseService implements Runnable {
    private String path;
    private String name;
    private String[] keywords;
    private List<String> result = new ArrayList<>();
    private boolean working;

    public TextFindService(String path, String name, String[] keywords) {
        this.path = path;
        this.name = name;
        this.keywords = keywords;
        this.working = true;
    }

    @Override
    public void run() {
        File file = new File(getPath() + getName());
        InputStreamReader reader = null;
        BufferedReader br = null;
        long time = System.currentTimeMillis();
        if (!file.exists()) {
            this.putLog(getName() + ":文件不存在");
            return;
        }
        this.putLog(getName() + ":开始搜索...");
        try {
            reader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8);

            br = new BufferedReader(reader);
            String line = null;
            int count = 0;
            while ((line = br.readLine()) != null) {
                if (!working) {
                    Thread.yield();
                    break;
                }
                boolean find = true;
                for (String kds : getKeywords()) {
                    if (!line.toLowerCase().contains(kds.toLowerCase())) {
                        find = false;
                        break;
                    }
                }
                if (find) {
                    getResult().add(line);
                    count++;
                }
            }
            this.putLog(getName() + ":完毕,找到" + count + "行数据");
        } catch (IOException e) {
            e.printStackTrace();
            this.putLog(e.getMessage());
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            working = false;
        }
        this.putLog(getName() + ":搜索结束...use time " + (System.currentTimeMillis() - time) + "ms");
    }

    private String getPath() {
        return path;
    }

    private String[] getKeywords() {
        return keywords;
    }

    public List<String> getResult() {
        return result;
    }

    public String getName() {
        return name;
    }

    public void stop() {
        this.working = false;
    }

    private void putLog(String data) {
        this.getResult().add(data);
        log(data);
    }

    public static void main(String[] args) {

        String path = "C:\\Users\\Downloads\\test\\";
        String name = "my.log";
        String keywords = "keywords";

        TextFindService find = new TextFindService(path, name, keywords.split(";"));
        find.run();
        for (String str : find.getResult()) {
            System.out.println(str);
        }

    }

    public boolean isDone() {
        return !working;
    }
}

这里面比较重要的就是run()函数中的源码,复杂搜索、工作状态判断、让权等;完成之后还不忘关闭文件句柄。

其中服务类main()主函数是我用来测试使用的,但这只能在源码里调试,添加一个GUI界面会更方便。

新增一个java swing GUI图形界面,这个工具更加遍历,不用每次都编写代码去检索。

Swing编程源代码:

package view;

import system.component.Button;
import system.component.TextEdit;
import system.component.TextView;
import system.conf.Constant;
import system.lib.CompactController;
import system.lib.IController;
import system.service.TextFindService;
import system.utils.DateTimeUtils;
import system.utils.StringUtils;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.io.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class LogSplitViewController extends CompactController implements IController, ActionListener, FocusListener {

    private TextEdit path, keywords;
    private JTextArea logs;

    private TextView labPath, labKey, labLogs, status;
    private Button start, stop;

    private static final String TIP_PATH = "Input the logs directory path.";
    private static final String TIP_KEYWORDS = "Multi keywords use ';' of symbol to split.";

    private List<TextFindService> findServiceList = new ArrayList<>();
    private String version = "20210903#v1.0";

    public LogSplitViewController() {
        super(680, 500);
    }


    @Override
    protected void createInit() {
        int x = 10, y = 10;
        path = new TextEdit();
        keywords = new TextEdit();
        logs = new JTextArea();
        path.setName("path");
        keywords.setName("keywords");

        labPath = new TextView("Directory:");
        labKey = new TextView("Keywords:");
        labLogs = new TextView("Logs:");
        status = new TextView("finished.");

        start = new Button("Analyse");
        stop = new Button("Break");

        labPath.setBounds(x, y, 80, 28);
        labKey.setBounds(x, y + 38, 80, 28);
        labLogs.setBounds(x, y + 76, 80, 28);

        path.setBounds(x + 65, y, 450, 32);
        keywords.setBounds(x + 65, y + 38, 450, 32);

        status.setBounds(0, y + 432, 680, 30);
        status.setBackground(Color.BLACK);
        status.setForeground(Color.green);

        JScrollPane scrollPane1 = new JScrollPane(logs);
        scrollPane1.setBounds(x + 40, y + 42 * 2, 600, 335);
        logs.setForeground(Color.green);
        logs.setBackground(Color.BLACK);

        start.setBounds(x + 530, y, 100, 32);
        stop.setBounds(x + 530, y + 38, 100, 32);

        this.setLayout(null);
        this.add(start);
        this.add(stop);
        this.add(path);
        this.add(keywords);
        this.add(status);
        this.add(scrollPane1);
        this.add(labLogs);
        this.add(labPath);
        this.add(labKey);

        start.addActionListener(this);
        stop.addActionListener(this);
        this.setTip(keywords, TIP_KEYWORDS);
        this.setTip(path, TIP_PATH);
        stop.setEnabled(false);
    }


    @Override
    public void init() {

    }

    @Override
    public void showX() {
        this.setTitle(Constant.TITLE_LOG_SPLIT + " - " + version);
        this.setResizable(false);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
        this.init();
    }

    @Override
    public void close() {

    }

    @Override
    public void hideX() {

    }

    private String[] keys() {
        String string = keywords.getText();
        if (string.contains(";")) {
            return string.split(";");
        }
        if (string.contains("|")) {
            return string.split("|");
        }
        return string.split(";");
    }

    private void initFind() {
        start.setEnabled(false);
        stop.setEnabled(true);
    }

    private void lastFind() {
        start.setEnabled(true);
        stop.setEnabled(false);
    }

    private void find() {
        try {
            initFind();
            checkFind();
            findBefore();

            File file = new File(path.getText());
            if (!file.exists()) {
                throw new Exception("The directory is don't exists.");
            }
            this.doFind(file.getPath() + "/", file.listFiles());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
//            lastFind();
        }
    }

    private void doFind(String path, File[] listFiles) {
        long time = System.currentTimeMillis();

        logPut("开始查找...path=" + path);
        String logname = DateTimeUtils.format(DateTimeUtils.getLocalDateTime(), "yyyyMMddHHmmss") + ".log";

        for (File file : listFiles) {
            logPut(" - 创建查找服务 " + file.getName());
            TextFindService service = new TextFindService(path, file.getName(), keys());
            findServiceList.add(service);
            new Thread(service).start();
        }


        new Thread(() -> {
            while (true) {
                if (System.currentTimeMillis() - time > 3600000) {
                    logPut("超时,放弃查找...");
                    break;
                }
                Iterator<TextFindService> iterator = findServiceList.iterator();
                if (!iterator.hasNext()) {
                    break;
                }
                while (iterator.hasNext()) {
                    TextFindService service = iterator.next();
                    if (service.isDone()) {
                        iterator.remove();
                        this.write(path, logname, service.getResult(), service.getName());
                    }
                }
            }
            logPut("查找完成!用时:" + (System.currentTimeMillis() - time) + "ms");
            lastFind();
        }).start();

    }

    private synchronized void write(String path, String logname, List<String> result, String name) {
        logPut(name + " 文件查找完成,写入到文件:" + logname);
        File file = new File(path + logname);
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(file, true);
            out.write(("--------------------------" + name + "------------------------------").getBytes());
            out.write("\n".getBytes());
            for (String s : result) {
                out.write(s.getBytes());
                out.write("\n".getBytes());
            }
            out.flush();
        } catch (IOException e) {
            e.printStackTrace();
            logPut(e.getMessage());
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            logPut("写入文件完成");
            logPut("还剩:" + findServiceList.size() + "个文件");

        }

    }

    private void breakFind() {
        logPut("breaking...");
        for (TextFindService service : findServiceList) {
            service.stop();
        }
        logPut("breaking done.");
        lastFind();
    }

    private void findBefore() {
        logs.setText("");
        findServiceList.clear();
    }

    private void checkFind() throws Exception {
        if (StringUtils.isEmptyTrim(path.getText()) || TIP_PATH.equals(path.getText())) {
            dialog(TIP_PATH);
            throw new Exception(TIP_PATH);
        }
        if (StringUtils.isEmptyTrim(keywords.getText()) || TIP_KEYWORDS.equals(keywords.getText())) {
            dialog("least one keyword");
            throw new Exception("least one keyword");
        }
    }

    private void setTip(TextEdit keywords, String tipKeywords) {
        if (!StringUtils.isEmptyTrim(keywords.getText())) {
            return;
        }
        keywords.setForeground(Color.gray);
        keywords.setText(tipKeywords);
        keywords.addFocusListener(this);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        Button button = (Button) e.getSource();
        if ("Analyse".equals(button.getName())) {
            find();
        } else if ("Break".equals(button.getName())) {
            breakFind();
        }
    }

    @Override
    public void focusGained(FocusEvent e) {
        TextEdit obj = ((TextEdit) (e.getSource()));
        if (TIP_KEYWORDS.equals(obj.getText())) {
            obj.setForeground(Color.black);
            obj.setText("");
        } else if (TIP_PATH.equals(obj.getText())) {
            obj.setForeground(Color.black);
            obj.setText("");
        }
    }

    @Override
    public void focusLost(FocusEvent e) {
        TextEdit obj = ((TextEdit) (e.getSource()));
        if ("path".equals(obj.getName()) && obj.getText().length() == 0) {
            setTip(obj, TIP_PATH);
        } else if ("keywords".equals(obj.getName()) && obj.getText().length() == 0) {
            setTip(obj, TIP_KEYWORDS);
        }
    }

    private void logPut(String msg) {
        logs.setText(logs.getText() + LocalDateTime.now().toString() + " " + msg + "\n");
        logs.setCaretPosition(logs.getDocument().getLength());
        status.setText(msg);
    }
}

现在来看一下效果:

QQ截图20210911100429

 

 

 
Copyright © 2008-2021 lanxinbase.com Rights Reserved. | 粤ICP备14086738号-3 |