`
lg_asus
  • 浏览: 184930 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

SWT初学写的小工具

 
阅读更多
背景:我们项目中多语言文件是放在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事件执行完才返回。
分享到:
评论

相关推荐

    初学SWT&JFace

    NULL 博文链接:https://softwarexiang120.iteye.com/blog/1488045

    自己动手写开发工具--基于Eclipse的工具开发

    最后以两个具有一定复杂程度的插件(Hibemate建模工具和界面设计器)为案例介绍了SwT、Draw2D、GEF、JET等技术的综合运用。 本书不仅适合于Eclipse插件开发初学者学习,对于有一定相关开发经验的开发人员也具有很高...

    初学SWT (一)

    NULL 博文链接:https://cuiran.iteye.com/blog/577547

    swt-designer开发教程

    此软件主要是八个pdf文档,是初学者学习swt开发的必备工具文档

    EJB写的工具管理系统(B/S,C/S混合)

    C/S的客户端使用jface和swt实现,也可以直接使用浏览器访问,适合EJB初学者学习,代码质量不错,大家可以看看

    JAVA上百实例源码以及开源项目源代码

     用JAVA编写了一个小工具,用于检测当前显示器也就是显卡的显示模式,比如分辨率,色彩以及刷新频率等。 Java波浪文字制作方法及源代码 1个目标文件 摘要:Java源码,初学实例,波浪文字  Java波浪文字,一个利用...

    java源码包---java 源码 大量 实例

     用JAVA编写了一个小工具,用于检测当前显示器也就是显卡的显示模式,比如分辨率,色彩以及刷新频率等。 Java波浪文字制作方法及源代码 1个目标文件 摘要:Java源码,初学实例,波浪文字  Java波浪文字,一个利用...

    java源码包2

     用JAVA编写了一个小工具,用于检测当前显示器也就是显卡的显示模式,比如分辨率,色彩以及刷新频率等。 Java波浪文字制作方法及源代码 1个目标文件 摘要:Java源码,初学实例,波浪文字  Java波浪文字,一个利用...

    java源码包3

     用JAVA编写了一个小工具,用于检测当前显示器也就是显卡的显示模式,比如分辨率,色彩以及刷新频率等。 Java波浪文字制作方法及源代码 1个目标文件 摘要:Java源码,初学实例,波浪文字  Java波浪文字,一个利用...

    java源码包4

     用JAVA编写了一个小工具,用于检测当前显示器也就是显卡的显示模式,比如分辨率,色彩以及刷新频率等。 Java波浪文字制作方法及源代码 1个目标文件 摘要:Java源码,初学实例,波浪文字  Java波浪文字,一个利用...

    成百上千个Java 源码DEMO 4(1-4是独立压缩包)

    数字证书:从文件中读取数字证书,生成文件输入流,输入文件为c:/mycert.cer,获取一个处理X.509证书的证书工厂…… Java+ajax写的登录实例 1个目标文件 内容索引:Java源码,初学实例,ajax,登录 一个Java+ajax写的...

    成百上千个Java 源码DEMO 3(1-4是独立压缩包)

    数字证书:从文件中读取数字证书,生成文件输入流,输入文件为c:/mycert.cer,获取一个处理X.509证书的证书工厂…… Java+ajax写的登录实例 1个目标文件 内容索引:Java源码,初学实例,ajax,登录 一个Java+ajax写的...

    JAVA上百实例源码以及开源项目

     用JAVA编写了一个小工具,用于检测当前显示器也就是显卡的显示模式,比如分辨率,色彩以及刷新频率等。 Java波浪文字制作方法及源代码 1个目标文件 摘要:Java源码,初学实例,波浪文字  Java波浪文字,一个利用...

    精通Eclipse

    Eclipse下SWT、Junit、Ant的使用方法以及Web应用开发;Eclipse下Struts、CVS的应用以及数据库构建和WebService应用开发;Eclipse下的Hibernate、Spring及其他插件的应用和开发;电子商务系统、管理信息系统、文件...

    Eclipse权威开发指南2.pdf

    8.5.1 标准小部件工具箱..... 205 8.5.2 JFace用户界面架构..... 206 8.6 Workbench架构...... 208 8.6.1 存储持久性值..... 209 8.6.2 使用胖客户端平台创建应用程序..... 209 8.6.3 使用并发性架构维持对用户...

    Eclipse权威开发指南3.pdf

    8.5.1 标准小部件工具箱..... 205 8.5.2 JFace用户界面架构..... 206 8.6 Workbench架构...... 208 8.6.1 存储持久性值..... 209 8.6.2 使用胖客户端平台创建应用程序..... 209 8.6.3 使用并发性...

    Eclipse权威开发指南1.pdf

    8.5.1 标准小部件工具箱..... 205 8.5.2 JFace用户界面架构..... 206 8.6 Workbench架构...... 208 8.6.1 存储持久性值..... 209 8.6.2 使用胖客户端平台创建应用程序..... 209 8.6.3 使用并发性...

    Visual C++ 编程资源大全(源码 窗体)

    用到了CSplitterWnd::DeleteView()和CSplitterWnd::CreateView()等成员函数(35KB)&lt;END&gt;&lt;br&gt;44,swt.zip DOS下仿WIN95界面及图标编辑器源程序(498k C&ASM 作者:添翼虎)(499KB)&lt;END&gt;&lt;br&gt;45,menutest.zip 定制WIN...

    Eclipse RCP Plug-in开发自学教程(Eclipse3.6)

    3,简单、全面,合适初学者入手 目录 1 富客户端平台 .....................................................................................................................................9 1.1 概述 .......

Global site tag (gtag.js) - Google Analytics