1. 程式人生 > 實用技巧 >Java IO流的簡單使用 通俗易懂 超詳細 【內含案例】

Java IO流的簡單使用 通俗易懂 超詳細 【內含案例】

IO流簡單使用

InputStream 位元組輸入流

OutputStream 位元組輸出流

Reader 字元輸入流

Writer 字元輸出流

程式碼示例

輸入和輸出是相對於程式來說的,讀取到程式中叫做輸入,寫到檔案中叫輸出.

InputStream 位元組輸入流

InputStream 位元組輸入流基類,是位元組輸入流所有類的超類

// 從輸入流中讀取資料中下一個位元組
abstract int read();

// 讀取一定數量的位元組,並將其緩衝到 b 陣列中
int read(byte[] b);

// 讀取最多 len 個位元組,並並將其緩衝到 b 陣列中
int read(byte[] b, int off, int len);

// 跳過或丟棄資料中 n 個位元組
long skip(lone n);

// 關閉流並釋放流關係中所有資源
void close();

OutputStream 位元組輸出流

OutputStream 位元組輸出流基類,是位元組輸出流所有類的超類

// 講指定的位元組寫入輸出流
abstract void write(int b);

// 將 b.length 個位元組從 b 中寫入輸出流中
void write(byte[] b);

// 將 b 陣列下標 off(b[off]) 後 len 個位元組寫入輸出流
void write(byte[] b, int off, int len)

// 重新整理輸出流並寫出所有緩衝的輸出位元組資料
void flush();

// 關閉輸出流,並釋放輸出流相關的資源
// 關閉之前,使用flush()寫出緩衝的位元組
void close();

Reader 字元輸入流

Reader 字元輸入流,是讀取字元流的抽象類

// 讀取單個字元
int read();

// 將字元讀入陣列
int read(char[] cbuf);

// 將 len 個字元讀到char陣列下標 off 後面
abstract int read(char[] cbuf, int off, int len);

// 跳過n個字元
long skip(long n);

// 關閉字元流,並釋放相關的資源
abstract void close();

Writer 字元輸出流

Writer 字元輸出流,是寫入字元流的抽象類

// 將 char 陣列寫入字元流
void write(char[] cbuf);

// 將 char 陣列下標 off 後 len 個字元寫入字元流
abstract void read(char[] cbuf, int off, int len);

// 寫入單個字元
void write(int c);

// 寫入字串
void write(Stirng str);

// 寫入字串的某一部分
// 也是將 string 轉成 char 然後執行 read(char[] cbuf, int off, int len);
void write(String str, int off, int len);

// 將指定的字元序列附加到此 Wirter
Writer append(CharSequence csq);

// 將指定字元序列的子序列追加到此 Writer
Writer append(CharSequence csq, int start, int end)

// 將指定字元追加到此 Writer
Writer append(char c);

// 重新整理流的緩衝
abstract void flush();

// 關閉流,但是要重新整理該流,否則關閉時會報錯 IOException
abstract void close();

例項

  • 例項不全,需自己動手探討其中的奧祕
  • 例項中使用了junit等註解,我在這裡貼一。也可以不用,就是吧log換成println多寫幾個類
<dependencies>
    <!--lombok 註解集合 -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.12</version>
    </dependency>
    <!-- logback 記錄日誌框架-->
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.2.3</version>
    </dependency>
    <!--Junit 單元測試框架-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13</version>
    </dependency>
</dependencies>

import lombok.extern.slf4j.Slf4j;
import org.junit.Before;
import org.junit.Test;
import java.io.*;

/**
 * @author http://cnblogs.com/beixuan
 */
@Slf4j
public class StreamTest {

    private static String fileName = "D:/Stream.txt";
    private static String fileName1 = "D:/Reader.txt";
    private static String fileName2 = "D:/紅色高跟鞋.mp3";

    @Before
    public void getFile(){
        File file = new File(fileName);
        if (!file.exists()){
            try {
                //建立檔案
                file.createNewFile();
                log.debug("建立檔案成功:{}", fileName);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        File file1 = new File(fileName1);
        if (!file1.exists()){
            try {
                //建立檔案
                file1.createNewFile();
                log.debug("建立檔案成功:{}", fileName1);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    /**
     * 位元組輸出流
     */
    @Test
    public void testOutputStream(){
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(fileName);
            fos.write("Hello world".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //重新整理緩衝區
            if (fos != null) {
                try {
                    fos.flush();
                    log.debug("寫入資料成功");
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 位元組輸入流
     */
    @Test
    public void testInputStream(){
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(fileName);
            int i = 0;
            StringBuffer sb = new StringBuffer();
            while ((i = fis.read()) != -1){
                // i是字元對應的ASCII碼
                sb.append((char) i);
            }
            log.debug("{}:\n{}", fileName, sb.toString());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    /**
     * 字元輸出流
     */
    @Test
    public void testWriter(){
        OutputStreamWriter osw = null;
        try {
            osw = new OutputStreamWriter(new FileOutputStream(fileName1));
            osw.write("可以輸出中文哦!\n\r\t還又'\\n\\r\\t'");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (osw != null){
                try {
                    osw.flush();
                    osw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 字元輸入流
     */
    @Test
    public void testReader(){
        // InputStreamReader 轉換流
        InputStreamReader isr = null;
        try {
            isr = new InputStreamReader(new FileInputStream(fileName2));
            StringBuffer sb = new StringBuffer();
            int i;
            while ((i = isr.read()) != -1){
                sb.append((char)i);
            }
            log.debug("{}:\n{}", fileName2, sb);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (isr != null){
                try {
                    isr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 高效流對比
     */
    @Test
    public void IoEquals() throws IOException{
        //操作的是一個3.19MB的音訊檔案 它們之間檔案越大,效果就越明顯

        /***********************************************************************/
        FileInputStream fis1 = new FileInputStream(fileName2);
        FileOutputStream fos1 = new FileOutputStream(fileName);
        int i;
        long startTime = System.currentTimeMillis();
        while ((i = fis1.read()) != -1){
            fos1.write(i);
        }
        long endTime = System.currentTimeMillis();
        log.debug("第一種高效流:{}", endTime - startTime);
        fos1.close();
        fis1.close();

        /***********************************************************************/
        FileInputStream fis2 = new FileInputStream(fileName2);
        FileOutputStream fos2 = new FileOutputStream(fileName);
        byte[] bytes = new byte[1024];
        startTime = System.currentTimeMillis();
        while ((i = fis2.read(bytes)) != -1){
            fos2.write(bytes, 0, i);
        }
        endTime = System.currentTimeMillis();
        log.debug("第二種高效流:{}", endTime - startTime);
        fos2.close();
        fis2.close();
        /***********************************************************************/

        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(fileName2));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(fileName));

        startTime = System.currentTimeMillis();
        while ((i = bis.read(bytes)) != -1){
            bos.write(bytes, 0, i);
        }
        endTime = System.currentTimeMillis();
        log.debug("第三種高效流:{}", endTime - startTime);
        bos.close();
        bis.close();
        /**
         *  第一種高效流:20186
         *  第三種高效流:30
         *  第二種高效流:10
         *  這麼對比下 BufferedInputStream BufferedOutputStream 是最好的配合
         */
    }
}

小結

  • 位元組流常用於圖片、音訊、視訊檔案及PPT、Word檔案.
  • 字元流常用於處理文字型別的檔案如txt、ini檔案等
  • 位元組流也可以處理純文字檔案,但字元流不可以處理圖片視訊等非純文字型別的檔案