天天看點

[Java IO]02_位元組流概要InputStreamOutputStream檔案位元組流記憶體操作流管道流資料操作流合并流

位元組流有兩個核心抽象類:InputStream 和 OutputStream。所有的位元組流類都繼承自這兩個抽象類。

InputStream 負責輸入,OutputStream 負責輸出。

位元組流主要操作byte類型資料。

以下為 JDK8 版本中位元組流的族譜圖:

具體詳情可檢視Java API文檔。 

由上圖可以看出,InputStream 和 OutputStream對于資料源的操作往往是成對出現的。 

InputStream的作用是用來表示哪些從不同資料源産生輸入的類。 

InputStream類型表

功能

構造器

ByteArrayInputStream

允許将記憶體的緩沖區當做InputStream使用

緩沖區,位元組将從中取出

StringBufferInputStream

将String轉換成InputStream

字元串。底層實作實際使用StringBuffer

FileInputStream

從檔案中讀取資訊

字元串,表示檔案名、檔案或FileDescriptor對象

PipedInputStream

産生用于寫入相關PipedOutputStream的資料。實作“管道化”概念

PipedOutputStream

SequenceInputStream

将多個InputStream對象合并為一個InputStream

兩個InputStream對象或一個容納InputStream對象的容器Enumeration

FilterInputStream

抽象類,作為“裝飾器”的接口。其中“裝飾器”為其他InputStream類提供有用功能

OutputStream決定了資料的輸出形式。

OutputStream類型表

ByteArrayOutputStream

緩沖區初始化尺寸(可選的)

FileOutputStream

FilterOutputStream

抽象類,作為“裝飾器”的接口。其中“裝飾器”為其他OutputStream類提供有用功能

檔案位元組流有兩個類:FileOutputStream 和 FileInputStream。

它們提供了方法将位元組寫入到檔案和将資料以位元組形式從檔案中讀取出來。

一般情形下,檔案位元組流操作遵循以下幾個步驟:

(1)使用File類綁定一個檔案。

(2)把File對象綁定到流對象上。

(3)進行讀、寫操作。 

(4)關閉輸入、輸出。

向檔案寫入資料

<a></a>

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.OutputStream;

public class FileOutputStreamDemo {

    public static void write1(OutputStream out, byte[] b) throws IOException {

        out.write(b); // 将内容輸出,儲存檔案

    }

    public static void write2(OutputStream out, byte[] b) throws IOException {

        for (int i = 0; i &lt; b.length; i++) { // 采用循環方式寫入

            out.write(b[i]); // 每次隻寫入一個内容

        }

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

        // 第1步、使用File類找到一個檔案

        File f = new File("d:" + File.separator + "test.txt"); // 聲明File對象

        // 第2步、通過子類執行個體化父類對象

        OutputStream out = new FileOutputStream(f); // 通過對象多态性,進行執行個體化

        // 執行個體化時,預設為覆寫原檔案内容方式;如果添加true參數,則變為對原檔案追加内容的方式。

        // OutputStream out = new FileOutputStream(f, true);

        // 第3步、進行寫操作

        String str = "Hello World\r\n"; // 準備一個字元串

        byte b[] = str.getBytes(); // 隻能輸出byte數組,是以将字元串變為byte數組

        write1(out, b);

        // write2(out, b);

        // 第4步、關閉輸出流

        out.close();

};

從檔案中讀取資料 

import java.io.FileInputStream;

import java.io.InputStream;

public class FileInputStreamDemo {

    public static void read1(InputStream input, byte[] b) throws IOException {

        int len = input.read(b); // 讀取内容

        System.out.println("讀入資料的長度:" + len);

    public static void read2(InputStream input, byte[] b) throws IOException {

        for (int i = 0; i &lt; b.length; i++) {

            b[i] = (byte) input.read(); // 讀取内容

    public static void read3(InputStream input, byte[] b) throws IOException {

        int len = 0;

        int temp = 0; // 接收每一個讀取進來的資料

        while ((temp = input.read()) != -1) {

            // 表示還有内容,檔案沒有讀完

            b[len] = (byte) temp;

            len++;

    public static void main(String args[]) throws Exception { // 異常抛出,不處理

        InputStream input = new FileInputStream(f); // 準備好一個輸入的對象

        // 第3步、進行讀操作

        // 有三種讀取方式,體會其差異

        byte[] b = new byte[(int) f.length()];

        read1(input, b);

        // read2(input, b);

        // read3(input, b);

        // 第4步、關閉輸入流

        input.close();

        System.out.println("内容為:\n" + new String(b)); // 把byte數組變為字元串輸出

ByteArrayInputStream 和 ByteArrayOutputStream是用來完成記憶體的輸入和輸出功能。

記憶體操作流一般在生成一些臨時資訊時才使用。 

如果臨時資訊儲存在檔案中,還需要在有效期過後删除檔案,這樣比較麻煩。

使用記憶體操作流完成一個轉換為小寫字母的程式 

import java.io.ByteArrayInputStream;

import java.io.ByteArrayOutputStream;

public class ByteArrayDemo {

    public static void main(String args[]) {

        String str = "HELLOWORLD";

        ByteArrayInputStream bis = new ByteArrayInputStream(str.getBytes()); // 記憶體輸入流

        ByteArrayOutputStream bos = new ByteArrayOutputStream(); // 記憶體輸出流

        // 用ByteArrayInputStream讀取字元串内容,

        // 全轉為小寫後,寫入ByteArrayOutputStream

        int temp = 0;

        while((temp = bis.read()) != -1) {

            char c = (char) temp; // 讀取的數字變為字元

            bos.write(Character.toLowerCase(c)); // 将字元變為小寫

        // 所有的資料就全部都在ByteArrayOutputStream中

        String newStr = bos.toString();    // 取出内容

        try {

            bis.close();

            bos.close();

        } catch(IOException e) {

            e.printStackTrace();

        System.out.println(newStr);

管道流的主要作用是可以進行兩個線程間的通信。

如果要進行管道通信,則必須把PipedOutputStream連接配接在PipedInputStream上。

為此,PipedOutputStream中提供了connect()方法。

import java.io.PipedInputStream;

import java.io.PipedOutputStream;

class Send implements Runnable {

    private PipedOutputStream pos = null; // 管道輸出流

    public Send() {

        this.pos = new PipedOutputStream(); // 執行個體化輸出流

    public void run() {

        String str = "Hello World!!!"; // 要輸出的内容

            this.pos.write(str.getBytes());

        } catch (IOException e) {

            this.pos.close();

    public PipedOutputStream getPos() { // 得到此線程的管道輸出流

        return this.pos;

class Receive implements Runnable {

    private PipedInputStream pis = null; // 管道輸入流

    public Receive() {

        this.pis = new PipedInputStream(); // 執行個體化輸入流

        byte b[] = new byte[1024]; // 接收内容

            len = this.pis.read(b); // 讀取内容

            this.pis.close(); // 關閉

        System.out.println("接收的内容為:" + new String(b, 0, len));

    public PipedInputStream getPis() {

        return this.pis;

public class PipedDemo {

        Send s = new Send();

        Receive r = new Receive();

            s.getPos().connect(r.getPis()); // 連接配接管道

        new Thread(s).start(); // 啟動線程

        new Thread(r).start(); // 啟動線程

資料操作流提供了格式化讀入和輸出資料的方法,分别為DataInputStream 和 DataOutputStream。

DataOutputStream

将格式化的訂單資料寫入到檔案

import java.io.DataOutputStream;

public class DataOutputStreamDemo {

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

        File f = new File("d:" + File.separator + "order.txt");

        DataOutputStream dos = new DataOutputStream(new FileOutputStream(f)); // 執行個體化資料輸出流對象

        String names[] = { "襯衣", "手套", "圍巾" }; // 商品名稱

        float prices[] = { 98.3f, 30.3f, 50.5f }; // 商品價格

        int nums[] = { 3, 2, 1 }; // 商品數量

        // 循環輸出

        for (int i = 0; i &lt; names.length; i++) {

            dos.writeChars(names[i]);

            dos.writeChar('\t');

            dos.writeFloat(prices[i]);

            dos.writeInt(nums[i]);

            dos.writeChar('\n');

        dos.close();

将訂單檔案中的格式化資料讀取出來

import java.io.DataInputStream;

public class DataInputStreamDemo {

    public static void main(String args[]) throws IOException { // 所有異常抛出

        DataInputStream dis = new DataInputStream(new FileInputStream(f)); // 執行個體化資料輸入流對象

        String name = null; // 接收名稱

        float price = 0.0f; // 接收價格

        int num = 0; // 接收數量

        char temp[] = null; // 接收商品名稱

        int len = 0; // 儲存讀取資料的個數

        char c = 0; // '\u0000'

            while (true) {

                temp = new char[200]; // 開辟空間

                len = 0;

                while ((c = dis.readChar()) != '\t') { // 接收内容

                    temp[len] = c;

                    len++; // 讀取長度加1

                }

                name = new String(temp, 0, len); // 将字元數組變為String

                price = dis.readFloat(); // 讀取價格

                dis.readChar(); // 讀取\t

                num = dis.readInt(); // 讀取int

                dis.readChar(); // 讀取\n

                System.out.printf("名稱:%s;價格:%5.2f;數量:%d\n", name, price, num);

            }

        } catch (Exception e) {

        dis.close();

合并流的主要功能是将多個InputStream合并為一個InputStream流。

合并流的功能由SequenceInputStream完成。

需要稍微留意的是,由前面的位元組流族譜圖,可以得知并沒有對應的OutputStream。

将兩個檔案内容合并為一個檔案

import java.io.SequenceInputStream;

public class SequenceDemo {

        // 第1步,綁定要操作的檔案

        InputStream is1 = new FileInputStream("d:" + File.separator + "a.txt"); // 輸入流1

        InputStream is2 = new FileInputStream("d:" + File.separator + "b.txt"); // 輸入流2    

        OutputStream os = new FileOutputStream("d:" + File.separator + "ab.txt"); // 輸出流

        // 第2步,綁定要合并的InputStream對象到SequenceInputStream

        SequenceInputStream sis = new SequenceInputStream(is1, is2); // 執行個體化合并流

        // 讀取兩個InputStream流的資料,然後合并輸出到OutputStream

        int temp = 0; // 接收内容

        while ((temp = sis.read()) != -1) { // 循環輸出

            os.write(temp); // 儲存内容

        // 第4步,關閉相關流

        sis.close();

        os.close();    

        is1.close();

        is2.close();

 本文轉自靜默虛空部落格園部落格,原文連結:http://www.cnblogs.com/jingmoxukong/p/4513964.html,如需轉載請自行聯系原作者