2015-04-02 52 views
3

我一直在爲此工作了幾天,現在我無法取得任何進展。我嘗試過使用Scanner和BufferedReader,但沒有運氣。使用BufferedReader翻譯字符串(Java)

基本上,我有,需要一個String並縮短其工作方法(shortenWord)按照此格式的文本文件:「你好」

hello,lo 
any,ne 
anyone,ne1 
thanks,thx 

這也說明了這樣的標點符號變成'lo?'等等。

我需要能夠讀取一個字符串並單獨翻譯每個單詞,所以「你好?任何人都謝謝!」將變成「低級ne1 thx!」,基本上使用我已經擁有的字符串中每個單詞的方法。我所擁有的代碼將會翻譯第一個單詞,但對其他單詞不起作用。我認爲這與我的BufferedReader的工作方式有關。

import java.io.*; 

public class Shortener { 
    private FileReader in ; 
    /* 
    * Default constructor that will load a default abbreviations text file. 
    */ 
    public Shortener() { 
     try { 
      in = new FileReader("abbreviations.txt"); 
     }  

     catch (Exception e) { 
      System.out.println(e); 
     } 
    } 

    public String shortenWord(String inWord) { 
     String punc = new String(",?.!;") ; 
     char finalchar = inWord.charAt(inWord.length()-1) ; 
     String outWord = new String() ; 
     BufferedReader abrv = new BufferedReader(in) ; 

      // ends in punctuation 
      if (punc.indexOf(finalchar) != -1) { 
       String sub = inWord.substring(0, inWord.length()-1) ; 
       outWord = sub + finalchar ; 


      try { 
       String line; 
       while ((line = abrv.readLine()) != null) { 
        String[] lineArray = line.split(",") ; 
         if (line.contains(sub)) { 
          outWord = lineArray[1] + finalchar ; 
          } 
         } 
        } 

      catch (IOException e) { 
       System.out.println(e) ; 
       } 
      } 

      // no punctuation 
      else { 
       outWord = inWord ; 

       try { 
       String line; 

        while((line = abrv.readLine()) != null) { 
         String[] lineArray = line.split(",") ; 
          if (line.contains(inWord)) { 
           outWord = lineArray[1] ; 
          } 
         } 
        } 

       catch (IOException ioe) { 
        System.out.println(ioe) ; 
       } 
      } 

     return outWord; 
    } 

    public void shortenMessage(String inMessage) { 
     String[] messageArray = inMessage.split("\\s+") ; 
     for (String word : messageArray) { 
      System.out.println(shortenWord(word)); 
     } 
    } 
} 

任何幫助,或者甚至在正確的方向微調將非常讚賞。

編輯:我試過在shortenWord方法結束時關閉了BufferedReader,它只是導致我在第一個表示BufferedReader關閉後的字符串中的每個單詞出現錯誤。

+0

在一個不相關的一面注:我想像這樣的詞縮寫是任何英語老師的噩夢燃料。 – 2015-04-02 10:23:08

+2

對於每個單詞都一遍又一遍地閱讀文件是毫無意義的,而且您實際上並沒有這樣做,因爲一旦您達到文件末尾,如果您沒有重新打開或倒帶它,它將停留在文件的結尾。更好的邏輯是打開文件,讀取一行,然後將替換應用到每個這樣的行。 – RealSkeptic 2015-04-02 10:25:53

+1

或將「翻譯」讀取到「Map 」中。另外爲什麼你在使用'String punc = new String(「,?。!;」);'而不是'String punc =「,?。!;」;'? – fabian 2015-04-02 10:33:00

回答

2

我認爲你可以有一個更簡單的解決方案,使用HashMap。當創建Shortener對象時,請將所有縮寫讀入地圖,並且只要您有單詞就引用它。這個詞將是key和縮寫value。就像這樣:

public class Shortener { 

    private FileReader in; 
    //the map 
    private HashMap<String, String> abbreviations; 

    /* 
    * Default constructor that will load a default abbreviations text file. 
    */ 
    public Shortener() { 
     //initialize the map 
     this.abbreviations = new HashMap<>(); 
     try { 
      in = new FileReader("abbreviations.txt"); 
      BufferedReader abrv = new BufferedReader(in) ; 
      String line; 
      while ((line = abrv.readLine()) != null) { 
       String [] abv = line.split(","); 
       //If there is not two items in the file, the file is malformed 
       if (abv.length != 2) { 
        throw new IllegalArgumentException("Malformed abbreviation file"); 
       } 
       //populate the map with the word as key and abbreviation as value 
       abbreviations.put(abv[0], abv[1]); 
      } 
     }  

     catch (Exception e) { 
      System.out.println(e); 
     } 
    } 

    public String shortenWord(String inWord) { 
     String punc = new String(",?.!;") ; 
     char finalchar = inWord.charAt(inWord.length()-1) ; 

     // ends in punctuation 
     if (punc.indexOf(finalchar) != -1) { 
      String sub = inWord.substring(0, inWord.length() - 1); 

      //Reference map 
      String abv = abbreviations.get(sub); 
      if (abv == null) 
       return inWord; 
      return new StringBuilder(abv).append(finalchar).toString(); 
     } 

     // no punctuation 
     else { 
      //Reference map 
      String abv = abbreviations.get(inWord); 
      if (abv == null) 
       return inWord; 
      return abv; 
     } 
    } 

    public void shortenMessage(String inMessage) { 
     String[] messageArray = inMessage.split("\\s+") ; 
     for (String word : messageArray) { 
      System.out.println(shortenWord(word)); 
     } 
    } 

    public static void main (String [] args) { 
     Shortener s = new Shortener(); 
     s.shortenMessage("hello? any anyone thanks!"); 
    } 
} 

輸出:

lo? 
ne 
ne1 
thx! 

編輯:

從atommans答案,你基本上可以去除shortenWord方法,通過修改shortenMessage方法是這樣的:

public void shortenMessage(String inMessage) { 
    for (Entry<String, String> entry:this.abbreviations.entrySet()) 
     inMessage = inMessage.replaceAll(entry.getKey(), entry.getValue()); 

    System.out.println(inMessage); 
} 
+0

哇!非常感謝你,這是完美的。我從來沒有使用過HashMaps,但這絕對看起來像我的問題的最簡單的實現:) – ectaylor 2015-04-02 11:09:22

+1

沒問題,我建議你閱讀他們一點。你會發現他們可以簡化許多解決方案,但對於一些解決方案來說也並非如此http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html – Ian2thedv 2015-04-02 11:16:02

+1

查看[Properties](http://docs.oracle.com/javase/7/docs) /api/java/util/Properties.html)。這樣你就不必自己解析文件。 – atomman 2015-04-02 11:26:29

3

所以我看着這個。首先,如果你要改變你的文本文件格式的選擇我會改變它的東西是這樣的(或XML):

key1=value1 
key2=value2 

這樣做,你以後可以使用Java的Properties.load(Reader)。這將消除任何手動解析文件的需要。'

如果通過任何更改,您沒有選擇更改格式,那麼您將不得不自己解析它。類似下面的代碼可以做到這一點,並將結果放入一個名爲shortningRulesMap,然後稍後可以使用它。

private void parseInput(FileReader reader) { 
    try (BufferedReader br = new BufferedReader(reader)) { 
     String line; 
     while ((line = br.readLine()) != null) { 
      String[] lineComponents = line.split(","); 
      this.shortningRules.put(lineComponents[0], lineComponents[1]); 
     } 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

當涉及到實際縮短的消息,我可能會選擇一個正則表達式的方法,e.g \\bKEY\\b,其中關鍵是你要縮短字。 \\b是正則表達式中的一個錨,並且代表word boundery,這意味着它不會匹配空格或標點符號。 然後做縮短了整個代碼會變得這樣的事情:

public void shortenMessage(String message) { 
    for (Entry<String, String> entry : shortningRules.entrySet()) { 
     message = message.replaceAll("\\b" + entry.getKey() + "\\b", entry.getValue()); 
    } 
    System.out.println(message); //This should probably be a return statement instead of a sysout. 
} 

全部放在一起會給你一些this,在這裏我爲測試目的添加了一個main

+0

我喜歡'replaceAll',不僅能夠有效地縮短單詞,還能夠編碼:P +1屬性 – Ian2thedv 2015-04-02 11:50:02

+0

我想實現這個功能,但是我有超過1個翻譯(例如其他語言)。我可以改變文本文件來使用'key1 = value1'而不是另一個分隔符。你能幫我和我的文章? [http://stackoverflow.com/q/40575394/1919069](http://stackoverflow.com/q/40575394/1919069)謝謝。 – euler 2016-11-23 01:12:42