1. 程式人生 > >用Java做一個及時翻譯工具

用Java做一個及時翻譯工具

                     

平時看英文文件或者查詢資料的時候,遇到了不懂的單詞,就要去百度,然後就會很麻煩。於是就想到用Java寫一個及時翻譯的小工具!

預期的實現效果: 雙擊選中一個單詞,按下Ctrl+C進行復制 然後馬上顯示出對應單詞的中文翻譯

首先基本思路是這樣的:

 
     
  • 首先獲取系統剪下板的內容
  •  
  • 將該內容傳送到網頁上,然後獲取網頁的原始碼,查詢到對應的中文解釋
  •  
  • 將中文翻譯顯示出來
  •  

以上就是基本的思路!但是實際操作的時候還是遇到了很大的困難的。

先寫兩個介面

得到剪下板的內容

這個並不是很困難,畢竟java有提供對應的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();//獲取系統剪貼簿        // 獲取剪下板中的內容
        Transferable clipT = clip.getContents(null);        if (clipT != null) {        // 檢查內容是否是文字型別        if (clipT.isDataFlavorSupported(DataFlavor.stringFlavor))        return (String)clipT.getTransferData(DataFlavor.stringFlavor);         }        return null;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

以上是放在一個工具類,做成靜態函式方便呼叫!

獲取網頁原始碼

首先想到是就是去百度翻譯

翻譯頁面

我們在這裡翻譯單詞 blue 我們看位址列http://fanyi.baidu.com/?aldtype=16047#en/zh/blue,剛好我們要翻譯的單詞就在最後,所以只要爬取頁面http://fanyi.baidu.com/?aldtype=16047#en/zh/待查單詞的原始碼,然後做一些篩選就可以了! 然後事情進展的卻並不是那麼的順利,百度的這個應該是為了防止爬取,所以翻譯的操作應該是Dom操作,原始碼上面毫無翻譯痕跡。 這個方法就終止了。

然後想到的是百度翻譯是否有開放介面 果然,百度翻譯提供了開放的介面,但是貌似要收費。 http://api.fanyi.baidu.com/api/trans/product/index 當然,我建議大家用這個方法,畢竟人家公司也不容易,而且功能也相對很豐富。

但是,如果真的不想花錢就不行了嗎?答案是否定的!

意外收穫 我在百度直接搜尋一個單詞的是否發現也會出現對應的翻譯!如下: 百度

然後檢視一下原始碼,搜尋藍色,果然,原始碼上面是有翻譯結果的(偷笑)。 找到了

而且對應的翻譯內容就在<span class="op_dict_text2"></span>之間! 百度搜索的url對應的是http://www.baidu.com/s?wd="搜尋內容"

於是就可以把獲取翻譯內容的工具類寫好了,程式碼如下:

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=";                        //百度搜索URL    private final static String TransResultStartFlag="<span class=\"op_dict_text2\">";      //翻譯開始標籤    private final static String TransResultEndFlag="</span>";                               //翻譯結束標籤    public static String getTranslateResult(String urlString) throws Exception {    //傳入要搜尋的單詞        URL url = new URL(PreUrl+urlString);            //生成完整的URL        // 開啟URL        HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();        // 得到輸入流,即獲得了網頁的內容        BufferedReader reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));        String preLine="";        String line;        int flag=1;        // 讀取輸入流的資料,並顯示        String content="";          //翻譯結果        while ((line = reader.readLine()) != null) {            //獲取翻譯結果的演算法            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;//返回翻譯結果    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

再寫一個窗體介面

注:有了上面的核心演算法,下面的其實都隨意實現了!

介面實現

我設計的窗體介面如下: 窗體

簡單說一下介面佈局:最上面一個JTextFieldJCheckBox,下面是JTextArea

簡單說一下各個控制元件的作用: JTextField:顯示待翻譯的單詞 JCheckBox:表示是從剪下板獲取單詞還是自己直接輸入 JTextArea:顯示翻譯結果

實現思路

介面已經實現完成了,那麼思路是什麼呢? 我的思路是這樣的:

  • 開啟一個執行緒,將JTextField裡面的值不斷設定為剪下板裡面的值
  • 如果JTextField裡面的值改變了(剪下板的值改變了,也就是選中複製了新的單詞),呼叫GetHtmlContentUtils 裡面的方法獲取翻譯的結果,並顯示!

對應程式碼如下:

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; // 記錄剪下板的內容    private JTextArea resContentTextField; // 記錄翻譯的內容    private JCheckBox translateFlag;       //標記單詞的獲取來源                                           //選中:手動輸入    未選中:剪下板獲取    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        //佈局設定        resContentTextField.setBorder(new LineBorder(new java.awt.Color(127, 157, 185), 1, false));        this.setLayout(new BorderLayout());        this.add(this.resContentTextField);        translateFlag.setToolTipText("手動輸入取詞");        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() {//設定JCheckBox的監聽            @Override            public void actionPerformed(ActionEvent e) {                // TODO Auto-generated method stub                if (translateFlag.isSelected()) {                    translateFlag.setToolTipText("自動複製取詞");    //設定提示                } else {                    translateFlag.setToolTipText("手動輸入取詞");                }            }        });        //監聽JTextField裡面內容改變的事件        srcContentTextField.getDocument().addDocumentListener(new DocumentListener() {                @Override            public void changedUpdate(DocumentEvent arg0) {            }            @Override            public void insertUpdate(DocumentEvent arg0) {    //內容改變                try {                    //呼叫介面獲取翻譯結果                    String result = GetHtmlContentUtils.getTranslateResult(srcContentTextField.getText());                    if (result == "")                        result = "!Sorry,未找到該詞!";                    resContentTextField.setText(result);//顯示翻譯結果                } catch (Exception e) {                    // TODO Auto-generated catch block                    resContentTextField.setText("!Sorry,未找到該詞!");                }            }            @Override            public void removeUpdate(DocumentEvent arg0) {            }        });        this.validate();    }    @Override    public void run() {        // TODO Auto-generated method stub        while (true) {            if (!translateFlag.isSelected()) {  //如果JCheckBox沒有被選中,則從剪下板獲取單詞                try {                    String content = ClipboradUtils.getClipboardText();                    srcContentTextField.setText(getSimpleWord(content));                } catch (Exception e) {                     // TODO Auto-generated catch block                    e.printStackTrace();                }            }            try {                Thread.sleep(1000);            } catch (InterruptedException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }    }    public static String getSimpleWord(String content) {//去掉切板裡面的一些特殊字元        return content.replace(".", "").replace(",", "")                .replace("'", "").replace(":", "")                .replace(";", "").trim();    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117

接下來就是main函數了,程式碼如下:

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);//設定在最頂層        mainFrame.setMinWindowLayout();        Thread t = new Thread(mainFrame);        t.start();    //開啟執行緒    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

程式執行結果

public

隨手翻譯了下 public 關鍵字,感覺還是可以的!

以下是2017/03/19日的補充 從eclipse匯出jar包時候,發現顯示的翻譯亂碼了。 找了半天的資料,有以下兩種解決方案:

  • 在控制檯執行:
 

java -Dfile.encoding=utf-8 -jar    C:\Users\lenovo\Desktop\TranslateTool.jar(可執行jar的路徑)

 

現在就可以在系統環境變數中增加一個變數,變數名為:    JAVA_TOOL_OPTIONS, 變數值為:-Dfile.encoding=UTF-8

這樣就基本可以解決亂碼問題。如果你有好的解決方案,歡迎留言 錯錯錯