I/O工做機制

數據發生流動,都會涉及到IO問題。在當今這個數據大爆炸時代,I/O 問題尤爲突出,很容易成爲一個性能瓶頸。html

JAVA中的I/O主要涉及到兩個方向:磁盤I/O工做機制,網絡I/O工做機制。java

I/O基本框架apache

Java 的 I/O 操做類在包 java.io 下,大概有將近 80 個類,可是這些類大概能夠分紅四組,分別是:api

  1. 基於字節操做的 I/O 接口:InputStream 和 OutputStream
  2. 基於字符操做的 I/O 接口:Writer 和 Reader
  3. 基於磁盤操做的 I/O 接口:File
  4. 基於網絡操做的 I/O 接口:Socket

前兩組主要是根據傳輸數據的數據格式,後兩組主要是根據傳輸數據的方式,雖然 Socket 類並不在 java.io 包下,可是我仍然把它們劃分在一塊兒,由於我我的認爲 I/O 的核心問題要麼是數據格式影響 I/O 操做,要麼是傳輸方式影響 I/O 操做,也就是將什麼樣的數據寫到什麼地方的問題,I/O 只是人與機器或者機器與機器交互的手段,除了在它們可以完成這個交互功能外,咱們關注的就是如何提升它的運行效率了,而數據格式和傳輸方式是影響效率最關鍵的因素了。咱們後面的分析也是基於這兩個因素來展開的。數組

基於字節的 I/O 操做接口

基於字節的 I/O 操做接口輸入和輸出分別是:InputStream 和 OutputStream,InputStream 輸入流的類繼承層次以下圖所示:網絡

輸入流根據數據類型和操做方式又被劃分紅若干個子類,每一個子類分別處理不一樣操做類型,OutputStream 輸出流的類層次結構也是相似,以下圖所示:多線程

圖 2. OutputStream 相關類層次結構oracle

java io的開始:文件框架

 

1. 咱們主要講的是流,流的本質也是對文件的處理,咱們按部就班一步一步從文件將到流去。ide

2. java 處理文件的類 File,java提供了十分詳細的文件處理方法。

另一個BLOG對文件File類有了進一步說明。

輸入流:從磁盤或網絡取得提供給程序(存放在內存)使用的數據。

輸出流:數據已經在程序中存在(內存),現要寫入到磁盤或者網絡。

我理解的「流」是一箇中介對象。經過它,磁盤和內存(buffer)實現交互。

字節輸出流:OutputStream  (抽象類)

方法:

close() 關閉輸出流

flush()  刷新緩衝區

write() ;向輸出流中寫入byte[]

write(int b) 向輸出流中寫入一個字節

FileOutputStream ;

 

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

/**
 * Created by li on 2016/10/24.
 * 1
 */
public class FileInputDemo {
    public static void main(String[] args) throws IOException {
        File file = new File("D:/asd.txt");
        if (!file.exists()) {
            System.out.println(file.createNewFile());
        }

        OutputStream outputStream = new FileOutputStream(file, true);
        outputStream.write("Hello Word".getBytes("utf-8"));
outputStream.close();
      //outputStream.write("Hello Word".getBytes("utf-8"));
}
}

注意任何流對象都應該關閉,關閉後再往裏面作讀寫錯字但是不能了。

OutputStream outputStream = new FileOutputStream(file, true);

設置爲true可在文件後追加,不然清空文件。

 

 

InputStream 

只有一個構造方法,僅僅用於建立對象。

方法

Methods 

Modifier and Type Method and Description
int

available()

返回輸入流指向的數據能被讀取或者跳過的字節大小。

 

void close()

關閉輸入流,關閉以後輸入流指向數據爲空,再作操做會報錯。

void mark(int readlimit)

標記屬於流位置。

boolean markSupported()

測試輸入流是否支持標記和重置方法。

abstract int read()

從輸入流指向的數據倉庫中讀取數據到內存。

int read(byte[] b)

讀取輸入流指向的數據到內存b字節中。

int read(byte[] b, int off, int len)

讀取指定長度字節

void reset()

重置標記。

long skip(long n)

跳讀輸入流指向數據。

 

import java.io.*;

/**
 * Created by li on 2016/10/24.
 * 1
 */
public class FileInputDemo {
    public static void main(String[] args) throws IOException {
        File file = new File("D:/asd.txt");
        if (!file.exists()) {
            System.out.println(file.createNewFile());
        }
        OutputStream outputStream = new FileOutputStream(file);
        outputStream.write("輸出輸出".getBytes());
        InputStream inputStream = new FileInputStream(file);
//        System.out.println(inputStream.available());
        byte[] bytes = new byte[1024];
        int len = inputStream.read(bytes);


        String s = new String(bytes, 0, len);
        System.out.println(s);
        inputStream.close();

    }
}

字符流不作介紹,注意 OutputStreamWriter 和InputStreamReader 可在字節流和字符流中變換。

內存操做流

 

ByteoutputStream 用於將內存中的數據輸出。 這個類的構造器好像是惟一不須要添加參數的IO類,其餘類能夠用它指定爲構造器輸入,作爲中介將數據傳輸給它,而後該對象有一個方法toByteArray()用於把輸入的東西轉爲字節數組。(搭配ObjectOutputStream使用)

ByteIntputStream 用於讀取數據到內存。

 

內存操做流通常用於生成一些臨時信息,假如不用內存操做流,臨時信息須要存放在文件中,比較麻煩。

如將對象轉爲二進制須要用到。

import com.sun.org.apache.xpath.internal.SourceTree;

import java.io.Serializable;

public class Preson implements Serializable {
    String name;

    void tell() {
        System.out.println("name is " + name);
    }
}
import java.io.*;
import java.time.Period;

public class Obj {


    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Preson preson = new Preson();
        preson.name = "lisi";
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
        objectOutputStream.writeObject(preson);
        byte[] bytes = byteArrayOutputStream.toByteArray();
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
        Preson object = (Preson) objectInputStream.readObject();
        object.tell();
        System.out.println(object.name);
    }
}

 

 

管道流:用於兩個線程之間通訊。 要進行輸出,必須把輸出流連在輸入流上。

代碼實例:

 

import java.io.IOException;
import java.io.PipedOutputStream;

public class pip extends Thread {

    private PipedOutputStream pipedOutputStream = null;

    public void send() {
        this.pipedOutputStream = new PipedOutputStream();
    }

    public PipedOutputStream getPipedOutputStream() {
        return pipedOutputStream;
    }

    @Override
    public void run() {
        String s = "Hello Word";
        try {
            this.pipedOutputStream.write(s.getBytes("utf-8"));
            this.pipedOutputStream.close();
            ;
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}
import java.io.IOException;
import java.io.PipedInputStream;

public class Get extends Thread {

    private PipedInputStream pipedInputStream = null;

    public void get() {
        this.pipedInputStream = new PipedInputStream();
    }

    public PipedInputStream getPipedInputStream() {
        return pipedInputStream;
    }

    @Override
    public void run() {
        byte[] bytes = new byte[1024];
        int len = 0;
        try {
            len = this.pipedInputStream.read(bytes);
            this.pipedInputStream.close();
            System.out.println(new String(bytes));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

public class Demo {
    public static void main(String[] args) throws IOException {
        pip pip1 = new pip();
        pip1.send();
        Get get = new Get();
        get.get();
        PipedInputStream pipedInputStream = get.getPipedInputStream();
        PipedOutputStream pipedOutputStream = pip1.getPipedOutputStream();
        pipedOutputStream.connect(pipedInputStream);
        pip1.start();
        get.start();
    }
}

現對此不作細糾。之後寫到多線程再說吧。

再列舉一些類  

數據操做流:DataOutputStream  主要針對數據進行操做

合併流:SequenceInputStream  將兩個文件合併爲一個文件。

壓縮流: ZipInpputStream 可將文件或文件夾壓縮爲ZIP,JAR,GZIP形式。

相關文章
相關標籤/搜索