如何把InputStream字節流和InputStreamReader字符流轉換成我們能看懂的String字符串

字節流和字符流讀取的文件的數據都是一堆我們人類看不懂的數字,熟悉ASCII表的可能還能看得懂英文字母(字符估計就夠嗆了),怎樣轉換一下讓我們能看的懂呢?方法有很多,下面將通過例子來逐一實現他們。

1、我們首先想到的恐怕非InputStreamReader了,把字節流轉成字符流不就行了嗎。

@Test
public void inputStream2String(){
    try (FileInputStream fis = new FileInputStream("test.txt");
         BufferedReader br = new BufferedReader(new InputStreamReader(fis))){
        StringBuilder sb = new StringBuilder();
        String line = null;
        boolean firstLine = true;
        while ((line = br.readLine())!=null){
            if (!firstLine){
                sb.append(System.getProperty("line.separator"));  //如果不是第一行,添加系統換行符
            } else {
                firstLine = false;
            }
            sb.append(line);
        }
        System.out.println(sb.toString());
    } catch (IOException e){
        e.printStackTrace();
    }
}

2、其實我們還有更簡單的方法,根本不用經過字節流,而且還省了對換行符的判斷。

@Test
public void inputStream2String(){
    try (FileInputStream fis = new FileInputStream("test.txt")){
        StringBuilder sb = new StringBuilder();
        byte[] bytes = new byte[1024];
        int len = 0;
        while ((len=fis.read(bytes))!=-1){
            sb.append(new String(bytes, 0, len));
        }
        System.out.println(sb.toString());
    } catch (IOException e){
        e.printStackTrace();
    }
}

3、上面的方法有很多重複性代碼是固定的,可以提出來,所以就有了第三方庫幫我們做好了這一切,使用Apache的IO庫,代碼會更簡潔。

這裏使用的是Maven加載的依賴,目前最新jar包是2017年的,還沒有出新的。添加的依賴如下:

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.6</version>
</dependency>

Java代碼很簡單

@Test
public void inputStream2String(){
    try (FileInputStream fis = new FileInputStream("test.txt")){
        String string = IOUtils.toString(fis, StandardCharsets.UTF_8);  //不指定編碼方式的toString在2.5被遺棄了
        System.out.println(string);
    } catch (IOException e){
        e.printStackTrace();
    }
}

IOUtils.toString的進一步封裝。

@Test
public void inputStream2String(){
    File file = new File("test.txt");
    try {
        //這個方法的底層還是使用的IOUtils.toString實現的
        //並且使用了try-with-resource,自動關閉流
        String string = FileUtils.readFileToString(file, StandardCharsets.UTF_8);
        System.out.println(string);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

這個類庫還有兩種方式具體代碼就不寫了,只把方法貼上:

  • IOUtils.readLines(final InputStream input, final Charset encoding)
  • Files.readLines(final File file, final Charset encoding) 這個方法是上面方法的封裝

4、既然你Apache實現了這個工具,那我Guava豈能甘爲人後。

@Test
public void inputStream2String(){
    try (FileInputStream fis = new FileInputStream("test.txt");
         BufferedReader bf = new BufferedReader(new InputStreamReader(fis))){
        //提示這是Beta版本,不穩定
        //接收的參數爲Readable
        String string = CharStreams.toString(bf);
        System.out.println(string);
    } catch (IOException e){
        e.printStackTrace();
    }
}

5、Guava還有一種方式,按行讀取。

@Test
public void inputStream2String(){
    try (FileInputStream fis = new FileInputStream("test.txt");
         InputStreamReader isr = new InputStreamReader(fis);
         BufferedReader br = new BufferedReader(isr)){
        List<String> stringList = CharStreams.readLines(br);
        System.out.println(stringList.toString());

    } catch (IOException e) {
        e.printStackTrace();
    }
}

6、使用Java7的java.nio.file.Files實現讀取,也很簡單。但是這個方法是一次性把文件所有內容全部讀進內存,容易造成stack overflow。

@Test
public void inputStream2String(){
    try{
        byte[] bytes = Files.readAllBytes(Paths.get("test.txt"));
        String string = new String(bytes);
        System.out.println(string);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

7、使用Jdk5的Scanner,同時支持英文和中文。

@Test
public void inputStream2String(){
    try (FileInputStream fis = new FileInputStream("test.txt")){
        Scanner scanner = new Scanner(fis, StandardCharsets.UTF_8);
        while (scanner.hasNext()){
            System.out.println(scanner.next());
        }
    } catch (IOException e){
        e.printStackTrace();
    }
}

8、最後一種權當了解,沒啥實際用途,只適合文件中包含英文字母或者字符的。

@Test
public void inputStream2String(){
    try (FileInputStream fis = new FileInputStream("test.txt")){
        int read = fis.read();
        while (read != -1){
            System.out.println("read = " + (char)read);
            read = fis.read();
        }
    } catch (IOException e){
        e.printStackTrace();
    }
}

總結

這麼多種方法,推薦使用apache或者gson的第三方庫。不過gson目前還是測試版本,悠着點。

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