用Java做一个及时翻译工具
平時(shí)看英文文檔或者查詢資料的時(shí)候,遇到了不懂的單詞,就要去百度,然后就會(huì)很麻煩。于是就想到用Java寫(xiě)一個(gè)及時(shí)翻譯的小工具!
預(yù)期的實(shí)現(xiàn)效果:
雙擊選中一個(gè)單詞,按下Ctrl+C進(jìn)行復(fù)制
然后馬上顯示出對(duì)應(yīng)單詞的中文翻譯
首先基本思路是這樣的:
- 首先獲取系統(tǒng)剪切板的內(nèi)容
- 將該內(nèi)容發(fā)送到網(wǎng)頁(yè)上,然后獲取網(wǎng)頁(yè)的源碼,查找到對(duì)應(yīng)的中文解釋
- 將中文翻譯顯示出來(lái)
以上就是基本的思路!但是實(shí)際操作的時(shí)候還是遇到了很大的困難的。
先寫(xiě)兩個(gè)接口
得到剪切板的內(nèi)容
這個(gè)并不是很困難,畢竟java有提供對(duì)應(yīng)的API,代碼如下:
package translate; import java.awt.Toolkit; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable;public class ClipboradUtils {protected static String getClipboardText() throws Exception{Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();//獲取系統(tǒng)剪貼板// 獲取剪切板中的內(nèi)容Transferable clipT = clip.getContents(null);if (clipT != null) {// 檢查內(nèi)容是否是文本類型if (clipT.isDataFlavorSupported(DataFlavor.stringFlavor))return (String)clipT.getTransferData(DataFlavor.stringFlavor); }return null;} }以上是放在一個(gè)工具類,做成靜態(tài)函數(shù)方便調(diào)用!
獲取網(wǎng)頁(yè)源碼
首先想到是就是去百度翻譯
我們?cè)谶@里翻譯單詞 blue
我們看地址欄http://fanyi.baidu.com/?aldtype=16047#en/zh/blue,剛好我們要翻譯的單詞就在最后,所以只要爬取頁(yè)面http://fanyi.baidu.com/?aldtype=16047#en/zh/待查單詞的源代碼,然后做一些篩選就可以了!
然后事情進(jìn)展的卻并不是那么的順利,百度的這個(gè)應(yīng)該是為了防止爬取,所以翻譯的操作應(yīng)該是Dom操作,源代碼上面毫無(wú)翻譯痕跡。
這個(gè)方法就終止了。
然后想到的是百度翻譯是否有開(kāi)放接口
果然,百度翻譯提供了開(kāi)放的接口,但是貌似要收費(fèi)。
http://api.fanyi.baidu.com/api/trans/product/index
當(dāng)然,我建議大家用這個(gè)方法,畢竟人家公司也不容易,而且功能也相對(duì)很豐富。
但是,如果真的不想花錢就不行了嗎?答案是否定的!
意外收獲
我在百度直接搜索一個(gè)單詞的是否發(fā)現(xiàn)也會(huì)出現(xiàn)對(duì)應(yīng)的翻譯!如下:
然后查看一下源代碼,搜索藍(lán)色,果然,源代碼上面是有翻譯結(jié)果的(偷笑)。
而且對(duì)應(yīng)的翻譯內(nèi)容就在<span class="op_dict_text2">和</span>之間!
百度搜索的url對(duì)應(yīng)的是http://www.baidu.com/s?wd="搜索內(nèi)容"
于是就可以把獲取翻譯內(nèi)容的工具類寫(xiě)好了,代碼如下:
package translate;import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL;public class GetHtmlContentUtils {private final static String PreUrl="http://www.baidu.com/s?wd="; //百度搜索URLprivate final static String TransResultStartFlag="<span class=\"op_dict_text2\">"; //翻譯開(kāi)始標(biāo)簽private final static String TransResultEndFlag="</span>"; //翻譯結(jié)束標(biāo)簽public static String getTranslateResult(String urlString) throws Exception { //傳入要搜索的單詞URL url = new URL(PreUrl+urlString); //生成完整的URL// 打開(kāi)URLHttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();// 得到輸入流,即獲得了網(wǎng)頁(yè)的內(nèi)容BufferedReader reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));String preLine="";String line;int flag=1;// 讀取輸入流的數(shù)據(jù),并顯示String content=""; //翻譯結(jié)果while ((line = reader.readLine()) != null) { //獲取翻譯結(jié)果的算法if(preLine.indexOf(TransResultStartFlag)!=-1&&line.indexOf(TransResultEndFlag)==-1){content+=line.replaceAll(" | ", "")+"\n"; //去電源代碼上面的半角以及全角字符flag=0;}if(line.indexOf(TransResultEndFlag)!=-1){flag=1;}if(flag==1){preLine=line;}}return content;//返回翻譯結(jié)果}}再寫(xiě)一個(gè)窗體界面
注:有了上面的核心算法,下面的其實(shí)都隨意實(shí)現(xiàn)了!
界面實(shí)現(xiàn)
我設(shè)計(jì)的窗體界面如下:
簡(jiǎn)單說(shuō)一下界面布局:最上面一個(gè)JTextField和JCheckBox,下面是JTextArea。
簡(jiǎn)單說(shuō)一下各個(gè)控件的作用:
JTextField:顯示待翻譯的單詞
JCheckBox:表示是從剪切板獲取單詞還是自己直接輸入
JTextArea:顯示翻譯結(jié)果
實(shí)現(xiàn)思路
界面已經(jīng)實(shí)現(xiàn)完成了,那么思路是什么呢?
我的思路是這樣的:
- 開(kāi)啟一個(gè)線程,將JTextField里面的值不斷設(shè)置為剪切板里面的值
- 如果JTextField里面的值改變了(剪切板的值改變了,也就是選中復(fù)制了新的單詞),調(diào)用GetHtmlContentUtils 里面的方法獲取翻譯的結(jié)果,并顯示!
對(duì)應(yīng)代碼如下:
package translate;import java.awt.BorderLayout; import java.awt.Container; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener;import javax.swing.JCheckBox; import javax.swing.JFrame; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.border.LineBorder; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener;public class MainFrame extends JFrame implements Runnable {private JTextField srcContentTextField; // 記錄剪切板的內(nèi)容private JTextArea resContentTextField; // 記錄翻譯的內(nèi)容private JCheckBox translateFlag; //標(biāo)記單詞的獲取來(lái)源//選中:手動(dòng)輸入 未選中:剪切板獲取private Container topContainer;public MainFrame() {//初始化控件srcContentTextField = new JTextField(10);resContentTextField = new JTextArea();translateFlag = new JCheckBox();topContainer = new Container();}public void setMinWindowLayout() {// TODO Auto-generated method stub//布局設(shè)置resContentTextField.setBorder(new LineBorder(new java.awt.Color(127, 157, 185), 1, false));this.setLayout(new BorderLayout());this.add(this.resContentTextField);translateFlag.setToolTipText("手動(dòng)輸入取詞");topContainer.setLayout(new BorderLayout());topContainer.add(srcContentTextField, BorderLayout.CENTER);topContainer.add(translateFlag, BorderLayout.EAST);this.add(this.topContainer, BorderLayout.NORTH);this.setResizable(false);translateFlag.addActionListener(new ActionListener() {//設(shè)置JCheckBox的監(jiān)聽(tīng)@Overridepublic void actionPerformed(ActionEvent e) {// TODO Auto-generated method stubif (translateFlag.isSelected()) {translateFlag.setToolTipText("自動(dòng)復(fù)制取詞"); //設(shè)置提示} else {translateFlag.setToolTipText("手動(dòng)輸入取詞");}}});//監(jiān)聽(tīng)JTextField里面內(nèi)容改變的事件srcContentTextField.getDocument().addDocumentListener(new DocumentListener() { @Overridepublic void changedUpdate(DocumentEvent arg0) {}@Overridepublic void insertUpdate(DocumentEvent arg0) { //內(nèi)容改變try {//調(diào)用接口獲取翻譯結(jié)果String result = GetHtmlContentUtils.getTranslateResult(srcContentTextField.getText());if (result == "")result = "!Sorry,未找到該詞!";resContentTextField.setText(result);//顯示翻譯結(jié)果} catch (Exception e) {// TODO Auto-generated catch blockresContentTextField.setText("!Sorry,未找到該詞!");}}@Overridepublic void removeUpdate(DocumentEvent arg0) {}});this.validate();}@Overridepublic void run() {// TODO Auto-generated method stubwhile (true) {if (!translateFlag.isSelected()) { //如果JCheckBox沒(méi)有被選中,則從剪切板獲取單詞try {String content = ClipboradUtils.getClipboardText();srcContentTextField.setText(getSimpleWord(content));} catch (Exception e) { // TODO Auto-generated catch blocke.printStackTrace();}}try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}public static String getSimpleWord(String content) {//去掉切板里面的一些特殊字符return content.replace(".", "").replace(",", "").replace("'", "").replace(":", "").replace(";", "").trim();} }接下來(lái)就是main函數(shù)了,代碼如下:
package translate;import javax.swing.JFrame;public class TranslateTool {public static void main(String[] args) {MainFrame mainFrame = new MainFrame();mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);mainFrame.setBounds(300, 200, 400, 300);mainFrame.setVisible(true);mainFrame.setAlwaysOnTop(true);//設(shè)置在最頂層mainFrame.setMinWindowLayout();Thread t = new Thread(mainFrame);t.start(); //開(kāi)啟線程} }程序運(yùn)行結(jié)果
隨手翻譯了下 public 關(guān)鍵字,感覺(jué)還是可以的!
以下是2017/03/19日的補(bǔ)充
從eclipse導(dǎo)出jar包時(shí)候,發(fā)現(xiàn)顯示的翻譯亂碼了。
找了半天的資料,有以下兩種解決方案:
- 在控制臺(tái)運(yùn)行:
java -Dfile.encoding=utf-8 -jar
C:\Users\lenovo\Desktop\TranslateTool.jar(可執(zhí)行jar的路徑)
- 設(shè)置JAVA_TOOL_OPTIONS:
有關(guān)JAVA_TOOL_OPTIONS,參考:
http://docs.oracle.com/javase/6/docs/platform/jvmti/jvmti.html#tooloptions
現(xiàn)在就可以在系統(tǒng)環(huán)境變量中增加一個(gè)變量,變量名為:
JAVA_TOOL_OPTIONS, 變量值為:-Dfile.encoding=UTF-8
這樣就基本可以解決亂碼問(wèn)題。如果你有好的解決方案,歡迎留言
軟件下載地址:下載及時(shí)翻譯工具
總結(jié)
以上是生活随笔為你收集整理的用Java做一个及时翻译工具的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 幼儿园观察记录的目的和目标_幼儿园观察记
- 下一篇: Java使用百度翻译api