我們在 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。
關於字符串亂碼問題:http://blog.csdn.net/hyde82/article/details/394768
1. 使用 JDK 5 的 Scanner 法
package cc.unmi.test; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import java.util.Scanner; 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; 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,"utf8")); String line = null; while((line = bufferedReader.readLine()) != null) { stringBuilder.append(System.getProperty("line.separator")); /r/n stringBuilder.append(line); } System.out.println(stringBuilder.toString()); } }
中間那些判斷是不是第一行來決定是否加換行符
JDK1.4 及之前的 readBytes 法
package cc.unmi.test; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; 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; public class Test { /** * @throws IOException 引入apache的io包 */ public static void main(String[] args) throws IOException { InputStream inputStream = new FileInputStream("d:/sample.txt"); String text = IOUtils.toString(inputStream,"UTF-8"); 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; 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.*; 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);
String content = new String(bytes,"gbk");//解決中文亂碼 System.out.println(text); } }
7.借助 ByteArrayOutputStream 法
InputStream inputStream = new FileInputStream("./outfile"); ByteArrayOutputStream baos = new ByteArrayOutputStream(); int i = -1; while ((i = inputStream.read()) != -1) { baos.write(i); } System.out.println(baos.toString());
8.JDK 7 的 NIO readAllBytes
byte[] bytes = Files.readAllBytes(Paths.get("d:/sample.txt")); String text = new String(bytes); System.out.println(text);
提供一個方法讀取:
/** * 通過文件名獲取內容【解決中文亂碼】 * @param fileName * @return */ public static String getFileContent(String fileName) { StringBuffer stringBuffer = new StringBuffer(); File file = new File(fileName); InputStream inputStream = null; // 文件輸入流 try { inputStream = new FileInputStream(file); InputStreamReader reader = new InputStreamReader(inputStream, "GBK"); // 最后的"GBK"根據文件屬性而定,如果不行,改成"UTF-8" BufferedReader br = new BufferedReader(reader); //BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"utf8")); String line; while ((line = br.readLine()) != null) { stringBuffer.append(line); } br.close(); reader.close(); } catch (Exception e) { e.printStackTrace(); } return stringBuffer.toString(); }
關於亂碼問題見 對Java字符類型的深入了解(轉貼)