Java IO之簡單輸入輸出

Java中的IO分爲兩個部分,以InputStream和Reader爲基類的輸入類,以OutputStream和Writer爲基類的輸出類。其中InputStream和OutputStream以字節爲單位進行IO,而Reader和Writer以字符爲單位。java

除了輸入輸出,還有一系列類庫稱爲Filter,或成爲裝飾器。對於輸入可用FilterInputStream和FilterReader的派生類,輸出可用FilterOutputStream和FilterWriter的派生類,其中FilterInputStream和FilterOutputStream以字節爲單位,FilterReader和FilterWriter以字符爲單位。緩存

還有一個獨立與InputStream和OutputStream的—RandomAccessFile,用於對文件的讀寫,有點相似與C語言中的fopen()markdown

因此能夠總結,全部以Stream結尾的都是以字節爲單位,也成爲流;以Reader或Writer結尾的都以字符爲單位。Reader和Writer在java1.1中才出現,若是須要進行轉換,能夠使用InputStreamReader和OutputStreamWriter。dom

過濾器(Filter)

Filter是對輸入或輸出進行必定的控制,如緩存、讀取或寫入基本數據類型等,用於更改流的一些行爲。spa

FilterInputStream的派生類:指針

這裏寫圖片描述

FilterOutputStream的派生類:日誌

這裏寫圖片描述

Reader和Writer中所用的Filter與InputStream和OutputStream中的Filter對比:code

這裏寫圖片描述

對於Filter的具體使用將在具體綜合例子中講到。對象

輸入

輸入分爲輸入字節和輸入字符,分別使用基類是InputStream和Reader,若是須要把InputStrema轉化爲Reader,能夠使用InputStreamReader。如下是一些InputStream經常使用的派生類與Writer與之對應的派生類。繼承

InputStream派生類:

這裏寫圖片描述

Reader與之對應的派生類:

這裏寫圖片描述

將InputStream轉成Reader示例:

// 建立一個InputStream類型的對象
InputStream in = new FileInputStream("data.txt");
// InputStreamReader繼承自Reader,其構造方法接受一個InputStream對象
Reader reader = new InputStreamReader(in);

輸出

輸出分爲輸出字節和輸出字符,分別使用基類是OutputStream和Writer,若是須要把OutputStrema轉化爲Writer,能夠使用OutputStreamWriter。如下是一些OutputStream經常使用的派生類與Writer與之對應的派生類。

OutputStream派生類:

這裏寫圖片描述

Writer與之對應的派生類:

這裏寫圖片描述

將OutputStream轉成Writer示例:

// 建立一個OutputStream類型的對象
OutputStream out=new FileOutputStream("data.txt");
// OutputStreamWriter繼承自Writer,其構造方法接受一個OutputStream對象
Writer writer=new OutputStreamWriter(out);

綜合示例

一、打開一個文件,並把其中的內容逐行輸出的屏幕上。爲了提升效率,這裏將使用第一種過濾器BufferedReader,可以對輸入進行緩衝。

public class Read {
    public static void main(String[]args) throws Exception{
        String file="data.txt";
        read(file);
    }

    public static void read(String file) throws Exception{
        BufferedReader in=new BufferedReader(new FileReader(file));
        String s;
        while((s=in.readLine())!=null)
            System.out.println(s);
        in.close();
    }
}

二、從文件中按字節讀取內容,須要用到DataInputStream過濾器,因爲這裏要對字節進行操做,因此要使用InputStream而不是Reader。其中對是不是用BufferedStream進行效率比較。

import java.io.*;

public class ReadByte {
    public static void main(String[] args) throws Exception {
        String file = "data.txt";
        long start;
        start = System.currentTimeMillis();// 記錄運行開始時間
        readWithBufferedInputStream(file);
        System.out.println("readWithBufferedInputStream use time:"
                + (System.currentTimeMillis() - start));// 運行結束時間-開始時間就是運行時間
        start = System.currentTimeMillis();
        readWithoutBufferedInputStream(file);
        System.out.println("readWithoutBufferedInputStream use time:"
                + (System.currentTimeMillis() - start));
    }

    public static void readWithBufferedInputStream(String file)
            throws Exception {
        // 用BufferedInputStream進行讀取文件
        DataInputStream in = new DataInputStream(new BufferedInputStream(
                new FileInputStream(file)));
        while (in.available() != 0)
            // DataInputStream剩餘的字符數不爲零則表示還沒輸出結束
            in.readByte();
        in.close();
    }

    public static void readWithoutBufferedInputStream(String file)
            throws Exception {
        // 不用BufferedInputStream讀取文件
        DataInputStream in = new DataInputStream(new FileInputStream(file));
        while (in.available() != 0)
            in.readByte();
        in.close();
    }
}

運行該程序,其中使用的data.txt文件大小爲5.4M,在個人電腦上的輸出爲:

readWithBufferedInputStream use time:8775
readWithoutBufferedInputStream use time:18487

顯然使用了BufferedInputStream效率高了很多。

三、java1.5之後爲了方便文件的輸入,添加了一個PrintWrite過濾器,它封裝了BufferedWriter,並且能夠接受String類型的文件名,因此能夠精簡代碼。

import java.io.*;
public class FileOutPut {
    public static void main(String[]args) throws Exception{
        BufferedReader in=new BufferedReader(new FileReader("data.txt"));
        PrintWriter out=new PrintWriter("data1.txt");
        String s;
        long start=System.currentTimeMillis();
        while((s=in.readLine())!=null){
            out.println(s);//用readLine讀取文件時,每一行的回車符會被去掉,因此寫入文件的時候要把回車符寫回去
        }
        System.out.println("use time:"+(System.currentTimeMillis()-start));
        in.close();
        out.close();
    }
}

運行文件同時能夠發現,一樣是同樣大的data.txt文件,讀出並寫出速度很是快,這個得益於緩存。

四、因爲以前的方法往文件裏面寫入的是字節或字符,沒有辦法存儲一些基本類型,因此要使用DataOutputStream/DataInputStream。

import java.io.*;

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

        DataOutputStream out = new DataOutputStream(new FileOutputStream(
                "data1.txt"));
        out.writeUTF("This a String");// 寫入字符串要用writeUTF();
        out.writeInt(5);
        out.writeFloat(5.4f);
        out.close();

        DataInputStream in = new DataInputStream(new FileInputStream(
                "data1.txt"));

        System.out.println(in.readFloat());
        System.out.println(in.readInt());
        System.out.println(in.readUTF());// 讀出字符串要用readUTF();
        in.close();
    }
}

五、使用RandomAccessFile進行讀寫文件有點相似DataOutputStream/DataInputStream,都須要指定數據類型。但RandomAccessFile在建立對象的時候須要肯定對文件的操做類型,r/w/rw分別表示只讀,只寫,讀和寫。Seek()方法能夠處處移動,在文件的任意位置修改內容

import java.io.*;

public class UsingRandomAccessFile {
    public static void main(String[] args) throws Exception {
        RandomAccessFile rf = new RandomAccessFile("data1.txt", "rw");
        rf.writeInt(5);
        rf.writeInt(10);
        rf.writeInt(15);
        rf.writeInt(24);
        rf.close();

        rf = new RandomAccessFile("data1.txt", "r");
        System.out.println(rf.readInt());
        System.out.println(rf.readInt());
        System.out.println(rf.readInt());
        System.out.println(rf.readInt());
        rf.close();

        rf = new RandomAccessFile("data1.txt", "rw");
        rf.seek(0);// 把指針指向文件開頭
        rf.writeInt(-1);// 把前兩個字節改爲-1
        rf.seek(0);
        System.out.println(rf.readInt());
        System.out.println(rf.readInt());
        System.out.println(rf.readInt());
        System.out.println(rf.readInt());
        rf.close();

    }
}

六、把標準輸入用BufferedReader包裝並獲取鍵盤輸入

public class Systemin {
    public static void main(String[] args) throws Exception {
        // System.in爲InputStream類型,要經過InputStreamReader將其轉換成Reader
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        String s;
        while ((s = in.readLine()) != null) {
            System.out.println(s);
        }
    }
}

六、重定向,把控制檯輸出、錯誤輸出定向到文件,可用來寫日誌文件

import java.io.*;

public class Redirect {

    public static void main(String[] args) throws Exception {
        OutputStream console = System.out;
        PrintStream out = new PrintStream(new BufferedOutputStream(
                new FileOutputStream("data1.txt")));
        BufferedReader in = new BufferedReader(new InputStreamReader(
                new FileInputStream("data.txt")));
        System.setOut(out);// 把輸出重定向到out
        System.setErr(out);// 把錯誤信息重定向到out
        String s;
        while ((s = in.readLine()) != null)
            System.out.println(s);// 輸出被定向到out,因此不會在控制檯輸出
        out.close();
        in.close();
    }

}
相關文章
相關標籤/搜索