如何用java有選擇的輸入多行文本

java如何有選擇的輸入多行文本

今天在作做業的時候碰到了一個問題:要用java作詞頻統計,可是這就犯難了,java如何有選擇性的進行文件輸入輸出呢?java

查閱文檔可知,inputStream類和outputStream類是字節流輸入輸出,而reader 類和writer 類則是直接Unicode碼輸入輸出,我爲了圖省事,我最後使用了FileReader類的read方法進行文件讀取。FileReader類中的read方法能夠逐字符讀取,返回類型爲int,其實就是0~255的char 類型,只要進行強制類型轉換,就能夠獲得讀入的字符,當遇到文件尾的時候,該方法返回-1。由於是char類型,因此若是遇到中文字符,好比句號,就會按照兩個char處理。正則表達式

 

接下來解決選擇性輸入的問題。思路很簡單:app

  1.若是如今所讀取到的字符不是咱們想要的,那麼就一直向下讀取,直到讀取到咱們想要的函數

  2.若是遇到了返回值爲-1的狀況,退出,表示文件讀取完成(這一步必定要放在中間判斷spa

  3.若是如今讀取的是咱們想要的,就一直讀取,直到出現咱們不須要的,退出,等待下一次讀取。code

解釋一下第二個爲何要在中間判斷吧。blog

由於若是放在三個判斷的第一個,那麼若是文件以無用的字符結尾,則最後一個單詞輸出後還會多餘輸出一個換行,由於return了一個空的StringBuffer,而輸出語句用的是println。文檔

若是放在三個判斷中的最後,那麼若是文件以有用單詞結尾,則最後一個單詞沒法輸出,由於掃描到單詞後緊接着就是read返回-1,此時就直接返回「字符串完成」,因此少最後一個單詞字符串

 

第一次解決的時候,由於判斷1的位置和判斷3混在了一塊兒,因此出現了最後一個單詞不能輸出的狀況。input

  錯誤寫法我也寫下來吧,以避免之後再錯:

錯誤1——放在最前面:

private String read() throws IOException{
        StringBuffer strBuf = new StringBuffer();
        int t=fileReader.read();
        if(t==-1) return "\\$";

錯誤2——放在最後:

1 while(t!=-1&&isAlph((char)t)){
2             strBuf.append((char) t);
3             t=fileReader.read();
4         }     
5     if(t==-1) return "\\$";
6     return strBuf.toString();
7 }

正確作法:(徹底代碼,而且簡化了不須要的流程)

 1 private String read() throws IOException{
 2         StringBuffer strBuf = new StringBuffer();
 3         int t=fileReader.read();
 4         if(t==-1) return "\\$";
 5         while(t!=-1&&isAlph((char)t)){
 6             strBuf.append((char) t);
 7             t=fileReader.read();
 8         }
 9         return strBuf.toString();
10     }

 

所以,能夠看到代碼的細節也是不容忽視的,同一句話,不一樣位置,致使結果截然不同。

 

======================================我是小清新的分割線=========================================

2016.5.8更新

嗯,好吧,我又來啦,此次的java之旅差很少就已經完成啦,如今讓咱們梳理一下此次學到的輸入流的組合方式:

除了上文中逐個字符進行輸入的方法以外,對於有些問題,正則表達式可能更加好用。

好比咱們想逐行讀取文本怎麼辦呢,咱們會發現FileReader類中是沒有這種方法的,所以咱們須要把File類和其餘輸入流組合起來,自力更生。好比咱們把File和Scanner類結合起來,熟悉控制檯的小夥伴們必定很清楚,Scanner經常使用來進行控制檯輸入,而且Scanner能夠一次讀取一行,所以,咱們就選它啦。

所以我麼能夠愉快地一次一行進行操做啦

定義以下:(in 和 out 分別是輸入流和輸出流)

public Tree_T_Display(File fin,File fout) throws IOException {
        in = new Scanner(new FileInputStream(fin));
        out = new FileWriter(fout);
}

這樣read()函數就能夠這樣定義啦:

public String read()throws IOException{
        if(in.hasNext()){
            String s = in.nextLine();
            s=s.replaceAll(" ", "");//去掉空格
            return s;
        }
        return null;
    }

這樣一來,配合正則表達式,咱們的代碼量能夠減小,而且在過濾數據方面也能夠交給正則表達式去作。

另外,正則表達式也提一下吧,在java的正則表達式我本身用過的有兩種調用方法,一種是String類中的split,matches方法,注意split方法中匹配上的字符不會出如今新的字符串中,而matches方法中的正則必須和字符串徹底匹配,不然就返回false。

另外,正則中,+表示1~n個(n)不限制,*表示0~n個,和{1,}  {0,}分別等價。

^表示行開頭,$表示行結尾,^在[]中表示「非」,取補集

舉例以下

目標:匹配「單詞」開頭+「(」結尾的字符串:

1 s.matches("^[a-zA-Z]+[^\\(]$")

匹配可能有特殊字符的單詞,縮寫等:

1 s.matches("^[^ ]+$")

這裏就用到了^在[]中的狀況,一個[]是一個可匹配的類,上面第二行做用是匹配一個「以非空格開頭而且以之爲結尾的字符串」

pte String read() throws IOException{
StringBuffer strBuf = new StringBuffer();
int t=fileReader.read();
if(t==-1) return "\\$";
while(t!=-1&&isAlph((char)t)){
strBuf.append((char) t);
t=fileReader.read();
}
//保留最大單詞長度,爲格式化輸出作準備
maxLen = maxLen < strBuf.length() ? strBuf.length() : maxLen;
return strBuf.toString();}
相關文章
相關標籤/搜索