2015-04-02 89 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