背景:我们项目中多语言文件是放在xml文件中,时间一长,一些多语言在代码中并没有用到,老大要我写个小工具将未使用到的多语言ID给找出来,需要考虑的就是:查找源代码文件的效率和判断ID是否被使用(注释中用到的不算),想用windows下的find findstr命令的,但java注释不好区分,因此还是只能对每个文件进行读取判断。
其中注释中出现ID的情况有以下几种情况:
1:// 开头的行,对应正则是 ^\\s*//.*
2:*开头的行,java的块注释中除首末两行其它是以*开头,对应正则是 ^\\s*\\*.*
3:/*开头的行,正则是 ^\\s*/\\*.*
4:*/结尾的行,正则 \\*/\\s*$
5:我把空行也认为是注释,正则 ^\\s+
第2种情况,有可能块注释中除首末外其它行并不以*开头,也是注释,因此这里比较麻烦,要在代码中判断。
代码如下:
public class FindStrInFiles implements Listener {
private Text msrText;
private Button msrBtn;
private Text projectText;
private Button projectBtn;
private ProgressBar progressBar;
private Button searchBtn;
private Text resultText;
private Label statusLabel;
private Pattern commentPattern;
private Matcher commentMatcher;
private BufferedReader br;
private String line;
private boolean preComment = false;
private Display display;
private Shell shell;
private LinkedList<String> msrList;
private boolean isUsed;
private WorkThread workThread;
private boolean isStopped;
private boolean isSuspended;
public static void main(String... args) {
FindStrInFiles find = new FindStrInFiles();
find.init();
}
private void init() {
// 以// * /*开头或者以*/结尾的都是注释,空行也认为是注释,
// 还有一种情况是在块注释中间的行,在Pattern中无法判断,需要在代码中单独判断
this.commentPattern = Pattern
.compile("(^\\s*//.*)|(^\\s*\\*.*)|(^\\s*/\\*.*)|(\\*/\\s*$)|(^\\s+)");
display = new Display();
shell = new Shell(display);
GridLayout layout = new GridLayout(3, false);
layout.horizontalSpacing = 10;
layout.marginLeft = layout.marginRight = layout.marginBottom = 5;
shell.setLayout(layout);
Label label = new Label(shell, SWT.NONE);
label.setText("多语言文件");
GridData gridData = new GridData(SWT.BEGINNING, SWT.CENTER, false,
false, 1, 1);
label.setLayoutData(gridData);
this.msrText = new Text(shell, SWT.BORDER | SWT.SINGLE);
gridData = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1);
gridData.heightHint = 18;
this.msrText.setLayoutData(gridData);
this.msrBtn = new Button(shell, SWT.BORDER | SWT.NONE);
this.msrBtn.setText("选择");
gridData = new GridData(SWT.BEGINNING, SWT.CENTER, false, false, 1, 1);
gridData.widthHint = 50;
this.msrBtn.setLayoutData(gridData);
this.msrBtn.addListener(SWT.Selection, this);
label = new Label(shell, SWT.NONE | SWT.UNDERLINE_SINGLE);
label.setText("工程父目录");
label.setForeground(display.getSystemColor(SWT.COLOR_BLUE));
label.setToolTipText("该目录下的所有项目中src下的源代码都会被搜索,不是工程的文件夹被忽略");
gridData = new GridData(SWT.BEGINNING, SWT.CENTER, false, false, 1, 1);
label.setLayoutData(gridData);
this.projectText = new Text(shell, SWT.BORDER | SWT.SINGLE);
gridData = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1);
gridData.heightHint = 18;
this.projectText.setLayoutData(gridData);
this.projectBtn = new Button(shell, SWT.BORDER);
this.projectBtn.setText("选择");
gridData = new GridData(SWT.BEGINNING, SWT.CENTER, false, false, 1, 1);
gridData.widthHint = 50;
this.projectBtn.setLayoutData(gridData);
this.projectBtn.addListener(SWT.Selection, this);
this.progressBar = new ProgressBar(shell, SWT.SIMPLE);
gridData = new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1);
this.progressBar.setLayoutData(gridData);
this.searchBtn = new Button(shell, SWT.BORDER);
this.searchBtn.setText("搜索");
this.searchBtn.addListener(SWT.Selection, this);
gridData = new GridData(SWT.BEGINNING, SWT.CENTER, false, false, 1, 1);
gridData.widthHint = 50;
this.searchBtn.setLayoutData(gridData);
label = new Label(shell, SWT.NONE);
label.setText("结果");
gridData = new GridData(SWT.BEGINNING, SWT.CENTER, false, true, 1, 1);
label.setLayoutData(gridData);
this.resultText = new Text(shell, SWT.BORDER | SWT.MULTI | SWT.H_SCROLL
| SWT.V_SCROLL | SWT.READ_ONLY);
gridData = new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1);
FontData fontData = new FontData();
fontData.setHeight(11);
this.resultText.setFont(new Font(display, fontData));
this.resultText.setLayoutData(gridData);
this.statusLabel = new Label(shell, SWT.NONE);
gridData = new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1);
this.statusLabel.setLayoutData(gridData);
shell.setBounds(100, 20, 800, 600);
shell.setDefaultButton(this.msrBtn);
shell.setText("搜索未使用的多语言ID");
shell.addListener(SWT.Dispose, this);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
shell.dispose();
}
@Override
public void handleEvent(Event event) {
int type = event.type;
Widget widget = event.widget;
if (SWT.Selection == type) {
if (widget == this.msrBtn) {
FileDialog dialog = new FileDialog(shell, SWT.SIMPLE | SWT.OPEN
| SWT.SINGLE);
dialog.setFilterPath("E:\\workspace\\eclipsej2ee3.7\\XXX\\conf");
dialog.setFilterExtensions(new String[] { "*.xml" });
String filePath = dialog.open();
if (filePath == null) {
return;
}
if (!dialog.getFileName().startsWith("message.")) {
MessageBox box = new MessageBox(shell, SWT.ICON_INFORMATION);
box.setText("Tip");
box.setMessage("选择的不是语言文件");
box.open();
return;
}
this.msrText.setText(filePath);
} else if (widget == this.projectBtn) {
DirectoryDialog dialog = new DirectoryDialog(shell, SWT.OPEN
| SWT.SINGLE);
dialog.setFilterPath("E:\\workspace\\eclipsej2ee3.7");
dialog.setMessage("选择工程父目录,该目录下的所有项目中src下的源代码都会被搜索,不是工程的文件夹被忽略");
String container = dialog.open();
if (container == null) {
return;
}
this.projectText.setText(container);
} else if (widget == this.searchBtn) {
String btnText = this.searchBtn.getText();
if ("搜索".equals(btnText)) {
String msr = msrText.getText().trim();
String father = projectText.getText().trim();
if (msr.length() == 0 || father.length() == 0) {
return;
}
this.resultText.setText("");
this.statusLabel.setText("");
this.isStopped = false;
workThread = new WorkThread(msr, father);
workThread.start();
this.searchBtn.setText("暂停");
} else if ("暂停".equals(btnText)) {
this.isSuspended = true;
this.searchBtn.setText("继续");
} else if ("继续".equals(btnText)) {
synchronized(this.msrList){
this.isSuspended = false;
this.msrList.notifyAll();
}
this.searchBtn.setText("暂停");
}
}
}
if (SWT.Dispose == type) {
this.isStopped = true;
display.dispose();
System.exit(0);
}
}
private void checkFile(final File project, final File src,
final String id) {
if (this.isStopped) {
return;
}
if(this.isSuspended){
synchronized(this.msrList){
try {
this.msrList.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
if (src.isDirectory()) {
File[] files = src.listFiles();
for (final File f : files) {
if (this.isUsed) {
return;
}
// 跳过类似.svn这样的目录
if (f.isHidden()) {
continue;
}
this.checkFile(project, f, id);
}
} else {
// 跳过非java文件
if (!src.getName().endsWith(".java")) {
return;
}
if (display.isDisposed()) {
return;
}
display.asyncExec(new Runnable() {
@Override
public void run() {
if (statusLabel.isDisposed()) {
return;
}
statusLabel.setText("查找ID: "+id+" 分析文件: " + src.getPath());
}
});
try {
br = new BufferedReader(new FileReader(src));
int index = -1;
while ((line = br.readLine()) != null) {
index++;
// 注释跳过
if (this.isComment(line)) {
} else {
if (line.indexOf("\"" + id + "\"") != -1) {
this.isUsed = true;
System.out.println(id + " occurs at project: "
+ project.getName() + ", file: "
+ src.getPath() + ", row number: " + index);
return;
}
}
}
} catch (IOException e) {
e.printStackTrace();
return;
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
private boolean isComment(String line) {
this.commentMatcher = this.commentPattern.matcher(line);
if (this.commentMatcher.matches()) {
// 注释块的第一行
if (line.trim().startsWith("/*")) {
this.preComment = true;
}
// 注释块的最后一行
if (line.trim().endsWith("*/")) {
this.preComment = false;
}
return true;
}
// 如果在注释块中间
if (this.preComment) {
return true;
}
return false;
}
private void setBtnStatus(final boolean flag) {
display.asyncExec(new Runnable() {
@Override
public void run() {
if (msrBtn.isDisposed() || projectBtn.isDisposed()) {
return;
}
msrBtn.setEnabled(flag);
projectBtn.setEnabled(flag);
}
});
}
// ==========================
class WorkThread extends Thread {
private String xmlPath;
private String container;
public WorkThread(String xmlPath, String container) {
this.xmlPath = xmlPath;
this.container = container;
}
@Override
public void run() {
setBtnStatus(false);
msrList = new LinkedList<String>();
Document doc = null;
try {
doc = new SAXBuilder().build(this.xmlPath);
} catch (JDOMException e1) {
e1.printStackTrace();
return;
} catch (IOException e1) {
e1.printStackTrace();
return;
}
Element root = doc.getRootElement();
List<Element> children = root.getChildren("msr");
if (children == null || children.size() == 0) {
return;
}
Iterator<Element> it = children.iterator();
while (it.hasNext()) {
msrList.add(it.next().getChildText("id"));
}
doc = null;
final File[] projects = new File(this.container).listFiles();
int msrIndex = 0;
int projectIndex = 0;
for (final String id : msrList) {
if (isStopped) {
return;
}
msrIndex++;
isUsed = false;
for (File f : projects) {
if (isStopped) {
return;
}
projectIndex++;
final int ratio = (int) ((projects.length * (msrIndex - 1) + msrIndex) / (projects.length
* msrList.size() / 100));
if (display.isDisposed()) {
return;
}
display.asyncExec(new Runnable() {
@Override
public void run() {
if (progressBar.isDisposed()) {
return;
}
progressBar.setSelection(ratio);
}
});
// 非目录则跳过
if (f.isFile()) {
continue;
}
// 不是工程则直接跳过
if (!new File(f, ".project").exists()) {
continue;
}
// 隐藏目录跳过
if (f.isHidden()) {
continue;
}
File src = new File(f, "src");
if (!src.exists()) {
continue;
}
checkFile(f, src, id);
if (isUsed) {
break;
} else {
}
}
if (!isUsed && !isStopped) {
if (display.isDisposed()) {
return;
}
display.asyncExec(new Runnable() {
@Override
public void run() {
if (resultText.isDisposed()) {
return;
}
resultText.append(id
+ System.getProperty("line.separator"));
}
});
}
}
setBtnStatus(true);
display.asyncExec(new Runnable() {
@Override
public void run() {
if (statusLabel.isDisposed()) {
return;
}
searchBtn.setText("搜索");
statusLabel.setText("搜索完毕,共有"
+ (resultText.getLineCount() - 1) + " 条记录");
}
});
}
}
}
这里遇到的几个问题:FileDialog和DirectoryDialog不能指定size和location, 如果想指定size和location,只能用Shell去模拟Dialog了。
还有两个常见的技术:在暂停搜索的时候,用了wait和notifyAll,由于搜索是个比较耗时的工作,因此不能直接在GUI线程中去完成,这里用WorkThread去完成搜索,由于swt和swing都是GUI 单线程机制,如果在GUI/EDT中去完成搜索的话,会造成UI假死。解决方法就是display.asyncExec和display.syncExec,SwintUtilities.invokeLater,SwingUtilities.invokeAndWait,前者表示直接让UI事件插队而返回,后者表示等待UI事件执行完才返回。
分享到:
相关推荐
本项目名为"java SWT简单小工具",显然是一个使用SWT库开发的简易应用程序示例。 在描述中,"java SWT简单小工具"被重复提及,这可能表明该项目专注于展示如何使用SWT库来构建简单的GUI(图形用户界面)应用。由于...
【初学SWT&JFace】—— 探索Java图形用户界面的新篇章 在Java编程领域,GUI(图形用户界面)开发是构建交互式应用程序的关键部分。SWT(Standard Widget Toolkit)与JFace是两个非常重要的库,它们为Java开发者提供...
这对于初学者或者希望了解SWT实际应用的开发者来说非常有价值,他们可以研究代码结构,学习如何使用SWT组件来构建用户界面,以及如何处理用户交互和数据管理。 至于“工具”标签,可能意味着这个通讯录程序除了基本...
对于初学者,可以先从理解SWT的基本组件和布局管理开始,然后逐渐深入到事件处理、自定义控件以及与其他Eclipse服务的集成等方面。同时,Window Builder的使用技巧也非常重要,例如熟悉其各种编辑模式、快捷键和预览...
SWT,全称Standard Widget Toolkit(标准小部件工具包),是IBM开发的一款用于Java编程的图形用户界面(GUI)工具包。它为Java应用程序提供了与操作系统更紧密集成的GUI组件,使开发者可以构建出与操作系统风格一致的...
通过实际的代码示例,作者向读者展示了SWT的基本用法,帮助初学者快速理解并掌握SWT的核心概念。 【标签】"源码"和"工具" "源码"标签表明我们将讨论的是具体的编程代码,而"工具"则指SWT作为一种用于构建图形用户...
本教程将深入探讨SWT库的使用方法和特性,帮助开发者更好地理解和应用这一强大的GUI工具。 ### SWT基础 1. **组件库**:SWT提供了丰富的组件,如按钮、文本框、列表、树视图、表格等,这些组件可以组合起来构建...
SWT(Standard Widget Toolkit)是Java编程中用于创建桌面应用程序用户界面的一种库,它是Eclipse项目的一部分,提供了丰富的图形...无论你是初学者还是有经验的开发者,这份资料都将是你探索和提升SWT技能的重要指南。
总的来说,SWT是Java开发原生风格GUI应用的一个强大工具,它结合了Java的跨平台性和原生界面的性能与美观。使用SWT时,开发者需要对Java、操作系统API以及Eclipse RCP有一定的了解,才能充分发挥其潜力。对于初学者...
Java SWT(Standard Widget Toolkit)是Java编程环境中用于创建桌面应用程序的一种图形用户界面(GUI)工具包。它是Eclipse基金会的一部分,提供了与操作系统本机UI组件紧密集成的能力,使得开发出的程序具有原生...
7. **Eclipse开发**:Eclipse作为SWT的主要使用者,其开发工具对SWT提供了很好的支持。学习如何在Eclipse环境中创建、调试和部署SWT应用是提升开发效率的关键。 8. **性能优化**:由于SWT直接操作系统资源,了解...
对于初学者,可以通过在线教程、官方文档和社区论坛学习如何使用SwTDesigner。理解Swing组件的性质和Eclipse插件的运作方式是关键,这将有助于更好地利用SwTDesigner进行开发。 总之,SwTDesigner是Java SE开发者的...
SWT的设计目标是提供一个高效、轻量级且与操作系统紧密集成的GUI工具包,它允许开发者创建出与操作系统平台风格一致的用户界面。在Eclipse IDE中,SWT是开发桌面应用程序的基础,它与JFace一起,构成了强大的图形...
本教程“SWT tutorial”针对SWT进行深入讲解,特别适合初学者学习。 SWT的核心概念是组件(Widgets),这些组件包括按钮、文本框、列表等,它们构成了GUI的基本元素。通过组合和配置这些组件,开发者可以创建各种...
**SWT API 深入解析** `SWT (Standard Widget Toolkit)` 是一个开源的Java图形用户界面(GUI)库,由Eclipse基金会维护。...无论是初学者还是经验丰富的开发者,深入学习SWT API都将为开发工作带来显著的效率提升。
这个"Java SWT教程"文档,特别提到的"SWT Designer"是一个强大的可视化设计工具,它极大地简化了使用SWT进行GUI开发的过程,对于初学者来说非常友好。 在Java GUI编程中,AWT(Abstract Window Toolkit)和Swing是...
总的来说,SWT为Java开发者提供了一种强大的工具,用于构建具有原生外观和高性能的GUI应用。通过这个SWT实例,初学者可以快速上手,熟练掌握GUI开发技术,进一步提升其Java编程能力。无论是简单的控制台应用还是复杂...
SWT作为GUI工具包,提供了丰富的组件,如按钮、文本框、列表、树视图等,用于构建用户界面。与Java Swing不同,SWT更接近于操作系统原生的UI,因此在性能和外观上都有优势。接下来,我们将深入探讨SWT的一些关键知识...