Java 裏把 InputStream 轉換成 String 的幾種方法

我們在 Java 中經常會碰到如何把 InputStream 轉換成 String 的情形,比如從文件或網絡得到一個 InputStream,需要轉換成字符串輸出或賦給別的變量。

未真正關注這個問題之前我常用的辦法就是按字節一次次讀到緩衝區,或是建立 BufferedReader 逐行讀取。其實大可不必費此周折,我們可以用 Apache commons IOUtils,或者是 JDK 1.5 後的 Scanner,還可用 Google  Guava 庫的 CharStreams。到了 JDK7,若要從文件中直接得到字符串還能用 java.nio.file.Files#readAllLines 和 java.nio.file.Files#readAllBytes 方法。

下面看各個例子,爲能夠實際用運,例子寫在 main 方法裏,並從文件獲得一個 InputStream,代碼中把可能要捕獲的異常拋出來。再就是注意處理輸入輸出流時有涉及到字符集,字符集亂了就亂碼了,默認字符集是 System.getProperty("file.encoding"),通常我們都用 UTF-8,異常 UnsupportedEncodingException 繼承自 IOException。

下面的 6 個方法中應該有一個你能看得上的吧,用 Groovy,Scala 的除外,若未找到一個遂意的,告訴我,你有好辦法更應該告訴我。

1. 使用 JDK 5 的 Scanner

package cc.unmi.test;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.InputStream;

import java.util.Scanner;

/** *  * @author Unmi * @Creation date: 2013-02-01 */

public class Test {   

 /**     * @param args     * @throws FileNotFoundException      */   

 public static void main(String[] args) throws FileNotFoundException {   

     InputStream inputStream = new FileInputStream("d:/sample.txt");    

    Scanner scanner = new Scanner(inputStream, "UTF-8");    

    String text = scanner.useDelimiter("\\A").next();      

  System.out.println(text);     

   scanner.close();  

  }

}

2. JDK1.4 及之前的 BufferedReader 法

package cc.unmi.test;

import java.io.BufferedReader;

import java.io.FileInputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

/** *  * @author Unmi * @Creation date: 2013-02-01 */

public class Test {  

  /**     * @param args     * @throws IOException      */    

public static void main(String[] args) throws IOException {       

 InputStream inputStream = new FileInputStream("d:/sample.txt");    

    StringBuilder stringBuilder = new StringBuilder();     

   BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));      

  boolean firstLine = true;      

  String line = null

      while((line = bufferedReader.readLine()) != null){        

    if(!firstLine){             

   stringBuilder.append(System.getProperty("line.separator"));     

       }else{            

    firstLine = false;     

       }         

   stringBuilder.append(line);  

      }    

    System.out.println(stringBuilder.toString());  

  }

}

中間那些判斷是不是第一行來決定是否加換行符是些雜音。

3. JDK1.4 及之前的 readBytes 法

package cc.unmi.test;

import java.io.FileInputStream;

import java.io.IOException;

import java.io.InputStream;

/** *  * @author Unmi * @Creation date: 2013-02-01 */

public class Test {   

 /**     * @throws IOException      */   

 public static void main(String[] args) throws IOException { 

       InputStream inputStream = new FileInputStream("d:/sample.txt");      

          byte[] buffer = new byte[2048];     

   int readBytes = 0;    

    StringBuilder stringBuilder = new StringBuilder();       

 while((readBytes = inputStream.read(buffer)) > 0){     

       stringBuilder.append(new String(buffer, 0, readBytes));     

   }              

  System.out.println(stringBuilder.toString()); 

   }

}

緩衝區的大小自己根據實際來調,比 BufferedReader 還簡潔些,不需管換行符的事情。

4. Apache commons IOUtils.toString 法

package cc.unmi.test;import java.io.*;import org.apache.commons.io.IOUtils;/** *  * @author Unmi * @Creation date: 2013-02-01 */public class Test { 

   /**     * @throws IOException      */   

 public static void main(String[] args) throws IOException {  

      InputStream inputStream = new FileInputStream("d:/sample.txt");   

     String text = IOUtils.toString(inputStream);   

     System.out.println(text);   

 }

}

第三方庫就是第三方庫,人家充分考慮到了你的感受,你對 JDK 庫的抱怨,多簡潔,一行搞定。IOUtils 還能把內容拷入其他的 Writer 中,如 IOUtils.copy(inputStream, new StringWriter())。

5. Google guava 的  CharStreams 方法

package cc.unmi.test;import java.io.*;

import com.google.common.io.CharStreams;

/** *  * @author Unmi * @Creation date: 2013-02-01 */

public class Test {   

 /**     * @throws IOException      */    

public static void main(String[] args) throws IOException {  

      InputStream inputStream = new FileInputStream("d:/sample.txt");     

   String text = CharStreams.toString(new InputStreamReader(inputStream, "UTF-8")); 

       System.out.println(text);  

  }

}

CharSteams 不是直接作用在 InputSteam 上的,還要靠 InputStreamReader 拱個橋。

6. JDK 7 的 NIO readAllBytes

package cc.unmi.test;

import java.io.IOException;

import java.nio.file.*;

/** *  * @author Unmi * @Creation date: 2013-02-01 */

public class Test {   

 /**     * @throws IOException      */  

  public static void main(String[] args) throws IOException {   

     byte[] bytes = Files.readAllBytes(Paths.get("d:/sample.txt"));    

    String text = new String(bytes); 

       System.out.println(text);  

  }

}

這讓我們相信 JDK  一直還有人在管,雖然不可能象動態語言的方法那麼快捷,上面的  readAllBytes 在處理大文件時肯定會很被動的。而 Files.readAllLines 會把文件的內容讀入一個 List<String> 對象中,往內存不斷放東西就得掂量下內存會不會被爆。在 java.nio.file.* 還有很多新事物可供發掘。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章