Java相关技术 - 文件内容检索工具
拿到一个几百M甚至上G的project让你去学习
有时候你会想知道某个关键词是在哪个文件里
比如:spring MVC配置的@RequestMapping,你从页面源知道了Action是 index/login.sftl
然后你想知道,这个@RequestMapping到底是配置在哪个Java类里,你怎么找到这个类呢
又比如,你想知道你当前看到的页面的源文件到底在项目的哪个路径下,你又要什么寻找
别告诉我,你会把项目里的文件一个个打开,直到找到你要的文件
如果每次都这么寻找你要的文件,那...
所以,下面的工具,应运而生了
附上源码及相关文件下载链接http://files.cnblogs.com/files/liaolongjun/FileChecker.zip
直接上界面图 (博客界面宽度不够,图片被自动缩放了,可右键图片另存为桌面看,效果会好N多)
看看执行结果图
整个工具就一个类。如果想方便的使用,可以做成自解压文件(.exe),如下图
FileChecker.exe就是自解压文件,放在桌面,双击即可运行
怎么制作自解压文件?
1.在桌面建一个文件夹: FileChecker
2.在FileChecker文件夹里再建一个文件夹:ace (ace是FileChecker.java所在的package)
3.将FileChecker.java放进上面的文件夹ace里
4.cmd下编译上面的java文件
比如我的:
a. cd C:\Users\Administrator\Desktop\FileChecker\ace
b. javac -sourcepath . -encoding utf-8 FileChecker.java (成功后,ace里会生成多个.class文件)
c. cd.. (返回上一级目录)
d. java -classpath . ace.FileChecker (执行class文件,看看效果)
看到界面后,就可以往下走了
5. 制作自解压文件
a. 写一个批处理文件,用来执行上面的class文件,很简单
(1)在FileChecker目录下新建一个txt文件,然后改名为 start.bat
(2)编辑方式打开start.bat
(3)在里面写上 java -classpath . ace.FileChecker
(4)保存
(5)双击运行start.bat (看到界面就OK了)
做到这一步,后面的也可以不用做了。可以把FileChecker整个文件夹移动到任何地方,然后在桌面创建start.bat的快捷方式,通过快捷方式运行即可
b. 自解压文件的后续步骤
这个相当简单,百度一下,分分钟搞定
代码:
package ace; import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent; import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.WindowConstants;
import javax.swing.filechooser.FileSystemView; /**
* 文件内容检索工具
*
* @author liaolongjun 2015年5月30日 下午2:39:07
*/
final class FileChecker { private FileChecker() {
init();
initFm();
initBtns();
initTextFileds();
initFileChooser();
initCheckBoxPanel();
initSeachLimitPanel();
initFileSelectPanel();
initOutputArea();
initListener();
add(checkBoxPanel, java, html, xml, jsp, js, css, isbreak, all);
add(seachLimitPanel, checkBoxPanel, tfSearchContent);
add(fileSelectPanel, btnSelect, tfFilePath, btnOK, btnClear, isAutoClear);
add(fm, seachLimitPanel, fileSelectPanel, scrollPane);
fm.setVisible(true);
fm.validate();
} private void init() {
try {
// 设置为当前操作系统的皮肤
String lookAndFeel = UIManager.getSystemLookAndFeelClassName();
UIManager.setLookAndFeel(lookAndFeel);
} catch (Exception e) {
outputException(e);
}
// 读取历史记录
URL url = FileChecker.class.getResource("history.properties");// 如果没有,则在当前class目录下创建
historyFile = url == null ? new File(FileChecker.class.getResource("").getPath() + "/history.properties") : new File(url.getPath());
props = new Properties();
try {
props.load(new FileInputStream(historyFile));
filePath = props.getProperty(HISTORY_SEARCH_PATH);
searchContent = props.getProperty(HISTORY_SEARCH_CONTENT);
} catch (Exception e) {
// outputException(e); // 抓到异常不处理
}
} private void initFm() {
fm = new JFrame("FILE CONTENT CHECKER . liaolongjun . ^(o o)^") {
private static final long serialVersionUID = 1L; protected void processWindowEvent(WindowEvent e) {
if (e.getID() == WindowEvent.WINDOW_CLOSING)
saveHistory(); // 关闭窗口前,先保存上一次的查询记录
super.processWindowEvent(e);
}
};
fm.setLayout(null);
fm.setSize(1000, 700);
fm.setResizable(false);
fm.setLocationRelativeTo(null);
fm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
Random ran = new Random();
// 每次打开时, 背景色都是随机的
fm.getContentPane().setBackground(new Color(ran.nextInt(255), ran.nextInt(255), ran.nextInt(255)));
} private void initOutputArea() {
outputArea = new JTextArea();
outputArea.setAutoscrolls(true);
// JTextArea 要放在 JScrollPane 里才有滚动效果(同JTable)
scrollPane = new JScrollPane(outputArea);
scrollPane.setBounds(7, 100, 980, 565);
} private void initFileSelectPanel() {
fileSelectPanel = new JPanel();
fileSelectPanel.setBounds(7, 55, 980, 40);
fileSelectPanel.setBackground(Color.white);
} private void initSeachLimitPanel() {
seachLimitPanel = new JPanel();
seachLimitPanel.setBounds(7, 5, 980, 45);
seachLimitPanel.setBackground(Color.white);
} /**
* 文件类型过滤(.suffix)
*/
private void initCheckBoxPanel() {
java = new JCheckBox("java", true);
html = new JCheckBox("html", true);
xml = new JCheckBox("xml");
jsp = new JCheckBox("jsp", true);
js = new JCheckBox("js");
css = new JCheckBox("css");
isbreak = new JCheckBox("isbreak", true); // 匹配到一个后是否跳出当前文件
isAutoClear = new JCheckBox("AUTOCLEAR", true); // 自动清除
all = new JCheckBox("all");// 全选
checkBoxPanel = new JPanel();
suffixs = new ArrayList<JCheckBox>();
fillSuffixs(java, html, xml, jsp, js, css);
} private void fillSuffixs(JCheckBox... cbs) {
for (JCheckBox cb : cbs)
suffixs.add(cb);
} private void initTextFileds() {
// 文件路径
tfFilePath = new JTextField(filePath);
tfFilePath.setPreferredSize(new Dimension(560, 30));
// 搜索内容
tfSearchContent = new JTextField(searchContent);
tfSearchContent.setPreferredSize(new Dimension(540, 30));
} private void initFileChooser() {
// 文件选择器设置桌面默认路径
fc = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory());
// 设置只能选择文件夹
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
} private void initBtns() {
btnSelect = new MyBtn("OPEN.....");
btnOK = new MyBtn("OK");
btnClear = new MyBtn("CLEAR");
} private void initListener() {
btnSelect.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (fc.showOpenDialog(fm) == JFileChooser.APPROVE_OPTION)
tfFilePath.setText(fc.getSelectedFile().toString());
}
});
btnOK.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// 点确定后,重置查询限制条件
resetLimitation();
if (filePath == null || filePath.trim().length() == 0)
JOptionPane.showMessageDialog(fm, "未指定路径");
else if (searchContent == null || searchContent.trim().length() == 0)
JOptionPane.showMessageDialog(fm, "未指定查询内容");
else
check(new File(filePath));
}
});
btnClear.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
outputArea.setText("");
}
});
all.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setAllSelected(all.isSelected(), suffixs);
}
});
} /**
* 重置查询的限制条件
*/
private void resetLimitation() {
exts = getExts();
isBreak = isbreak.isSelected();
filePath = tfFilePath.getText();
searchContent = tfSearchContent.getText();
} /**
* 获取要限制查找范围的文件后缀名(文件扩展名)
*/
private List<String> getExts() {
List<String> exts = new ArrayList<String>();
for (JCheckBox cb : suffixs)
if (cb.isSelected())
exts.add(cb.getText());
return exts.size() > 0 ? exts : null; // 如果没有文件限制,返回null
} /**
* 是否全选
*/
private void setAllSelected(boolean boo, List<JCheckBox> cbs) {
for (JCheckBox cb : cbs)
cb.setSelected(boo);
isbreak.setSelected(boo); // isbreak不在suffixs里, 所以在这里单独设置上
} /**
* 添加组件
*/
private void add(Container parent, JComponent... components) {
for (JComponent c : components)
parent.add(c);
} /**
* 保存查询痕迹
*/
private void saveHistory() {
try {
props.setProperty(HISTORY_SEARCH_PATH, filePath == null ? "" : filePath);
props.setProperty(HISTORY_SEARCH_CONTENT, searchContent == null ? "" : searchContent);
props.store(new FileOutputStream(historyFile), "--no comment--");
} catch (IOException e) {
e.printStackTrace();
}
} /**
* 打印异常信息
*/
private void outputException(Exception e) {
outputArea.append(e + "\n");
for (StackTraceElement s : e.getStackTrace())
outputArea.append(" " + s + "\n");
} /**
* 检索的文件数目
*/
private int numFiles;
/**
* 满足查询条件的数目
*/
private int numResults; private void check(final File file) {
if (isAutoClear.isSelected())
btnClear.doClick();
outputArea.append("文件检索中......\n\n");
numFiles = 0;
numResults = 0;
new Timer().schedule(new TimerTask() {
public void run() {
try {
if (exts == null)
check1(file);
else
check2(file);
outputArea.append("\n*\n* 执行结束,一共检索了 " + numFiles + " 个文件。 符合条件:" + numResults + "\n*\n");
outputArea.append("\nHISTORY:" + historyFile + "\n\n");
} catch (Exception e) {
outputException(e);
}
JScrollBar jscrollBar = scrollPane.getVerticalScrollBar();
jscrollBar.setValue(jscrollBar.getMaximum());
}
}, 50);
} /**
* 没有文件类型限制
*/
private void check1(File file) throws IOException {
File[] files = file.listFiles();
for (File f : files)
if (f.isFile())
read(f);
else
check1(f);
} /**
* 有文件类型限制
*/
private void check2(File file) throws IOException {
File[] files = file.listFiles();
for (File f : files)
if (f.isFile()) {
String ext = getExt(f);
if (ext != null && exts.contains(ext))
read(f);
} else
check2(f);
} /**
* 获取文件后缀(文件扩展名)
*/
private String getExt(File file) {
String fileName = file.getName();
return fileName.lastIndexOf(".") == -1 ? null : fileName.substring(fileName.lastIndexOf(".") + 1);
} private void read(File file) throws IOException {
numFiles++;
FileReader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
String str;
int rowNum = 0; // 行号
if (isBreak)
while ((str = br.readLine()) != null) {
rowNum++;
if (str.indexOf(searchContent) != -1) {
numResults++;
outputArea.append(file.toString() + "\n" + " 行号: " + rowNum + " " + str + "\n");
break;
}
}
else {
StringBuilder sb = new StringBuilder(file.toString() + "\n");
boolean flag = false;
while ((str = br.readLine()) != null) {
rowNum++;
if (str.indexOf(searchContent) != -1) {
flag = true;
sb.append(" 行号: " + rowNum + " " + str + "\n");
}
}
if (flag) {
numResults++;
outputArea.append(sb.toString());
}
}
br.close();
} /**
* 订制规格一致的按钮
*/
private class MyBtn extends JButton {
private static final long serialVersionUID = 1L; public MyBtn(String btnName) {
super(btnName);
setPreferredSize(new Dimension(100, 30));
}
} /**
* 保存上一次查询痕迹的文件
*/
private File historyFile;
private Properties props;
private String filePath;
private String searchContent;
private final String HISTORY_SEARCH_PATH = "historySearchPath";
private final String HISTORY_SEARCH_CONTENT = "historySearchContent";
private List<JCheckBox> suffixs;
private List<String> exts;
private boolean isBreak; /**
* JFileChooser 文件选择组件
*/
private JFileChooser fc;
/**
* 文件类型
*/
private JCheckBox java, html, xml, jsp, js, css, isbreak, all, isAutoClear;
/**
* 内容输出区域
*/
private JTextArea outputArea;
private JScrollPane scrollPane;
private JFrame fm;
private JButton btnSelect, btnOK, btnClear;
private JTextField tfSearchContent, tfFilePath;
private JPanel checkBoxPanel, seachLimitPanel, fileSelectPanel; public static void main(String[] args) {
new FileChecker();
}
}
补充一句:运行时,会在ace文件夹里生成一个history.properties文件,用于保存最后一次的检索痕迹。下次运行的时候,会自动显示你上次查询的痕迹(不是查询的结果)
打完,收工!
附上源码及相关文件下载链接http://files.cnblogs.com/files/liaolongjun/FileChecker.zip
经验总结
1、图标:找到系统图标的文件,用解压缩软件打开,取出里面的图片文件夹
2、编译java文件的bat文件写法:
1) cd C:\Users\Administrator\Desktop\FileChecker\ace
2) javac -sourcepath . -encoding utf-8 FileChecker.java
3、运行class文件的bat写法:java -classpath . ace.FileChecker (可在上一步完成后,cd.. 然后执行这一步的命令来运行)
4、properties文件里输入汉字会自动转化为ASCII编码,可免中文乱码的烦恼