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


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

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

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

 

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

  1.如果現在所讀取到的字符不是我們想要的,那么就一直向下讀取,直到讀取到我們想要的

  2.如果遇到了返回值為-1的情況,退出,表示文件讀取完成(這一步一定要放在中間判斷

  3.如果現在讀取的是我們想要的,就一直讀取,直到出現我們不需要的,退出,等待下一次讀取。

解釋一下第二個為什么要在中間判斷吧。

因為如果放在三個判斷的第一個,那么如果文件以無用的字符結尾,則最后一個單詞輸出后還會多余輸出一個換行,因為return了一個空的StringBuffer,而輸出語句用的是println。

如果放在三個判斷中的最后,那么如果文件以有用單詞結尾,則最后一個單詞無法輸出,因為掃描到單詞后緊接着就是read返回-1,此時就直接返回“字符串完成”,所以少最后一個單詞

 

第一次解決的時候,因為判斷1的位置和判斷3混在了一起,所以出現了最后一個單詞不能輸出的情況。

  錯誤寫法我也寫下來吧,以免以后再錯:

錯誤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();
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM