Java IO流大家族(總結)

目錄

1.IO流的分類

1.1  通過流分類:輸入流,輸出流

1.2  通過數據單位不同分分類:字符流,字節流

1.3  抽象類

1.4  各抽象類的選用

2.文件流的使用

2.1  字節輸出流:FileOutputStream

2.2 字節輸入流:FileInputStream

2.3 緩衝區類(高效類):BufferedOutputStream,BufferedInputStream

3.轉換流的使用

3.1 字節流轉化爲字符流:OutputStreamWriter,InputStreamReader

3.2 OutputStreamWriter,InputStreamReader的封裝類(簡化寫法):FileWriter,FileReader

3.3 緩衝區類(高效類):BufferedWriter,BufferedReader

4.數據輸入輸出流 

5.內存操作流

6.打印流

7.標準輸入輸出流

8.隨機訪問流

9.合併流

10.序列化流反序列化流

11.Properties


1.IO流的分類

1.1  通過流分類:輸入流,輸出流

輸入流:從接收器輸入到java程序。

輸出流:輸出流接受輸出字節並將這些字節發送到某個接收器,也就是從java程序輸出到接收器。

1.2  通過數據單位不同分分類:字符流,字節流

在java版本中是先有字節流,再有字符流,1字符 = 2字節

字節流:每次傳輸一個字節,一箇中文漢字是兩個字節,會出現亂碼。

字符流:每次傳輸兩個字節,一般傳輸中文

1.3  抽象類

字節輸出流:OutputStream

字節輸入流:InputStream

字符輸出流:Writer

字符輸入流:Reader

1.4  各抽象類的選用

選用輸入,輸出流通過需求選用

選用字符,還是字節,一般用記事本打開是看得懂的用字符,看不懂的用字符。字節流更加適用於音頻文件、圖片、歌曲。

2.文件流的使用

2.1  字節輸出流:FileOutputStream

向文件中寫入數據

public static void main(String[] args) throws IOException {
        //追加寫入,append爲true追加
        FileOutputStream fos = new FileOutputStream("E:\\b.txt",true);

        byte[] b = {'a','b','c','d'};
        fos.write(97);//底層是二進制數據,記事本會找到對應的字符值
        fos.write("\n".getBytes());//加入換行,一般windows寫法是\r\n,linux是\n,mac是\r
        fos.write("hello,world".getBytes());
        fos.write("\n".getBytes());
        fos.write(b,1,2);
        fos.write("\n".getBytes());

        fos.close();
    }

程序分爲三部分:

(1)創建字節輸出流對象:這一步創建了文件,創建了fos對象,並把fos對象指向了此文件

(2)寫入數據

(3)釋放資源:釋放了文件所佔用的相關資源,變成垃圾,通知系統回收

異常處理方式:

異常有很多變形,這裏用try...catch...catch...finally...(這裏fos可能爲空,如當找不到指定的盤符是,或者說是我只有一個C盤,得到fos爲空)

public static void main(String[] args) {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream("E:\\b.txt",true);
            fos.write("異常處理".getBytes());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(fos != null){//fos不爲空才執行,因爲finally是默認執行的
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

2.2 字節輸入流:FileInputStream

讀取文件:一次讀取一個字節:int read()

public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("E:\\b.txt");
        int by = 0;
        //讀取,賦值,判斷
        while((by=fis.read())!=-1){
            System.out.print((char) by);
        }
        fis.close();
    }

讀取文件如果沒有相應文件不會爲你創建文件,這裏用的 int read().一次傳輸一個字節,返回的是數據字節,當返回值爲-1,則表示傳輸結束,漢字是兩個字節,會被拆分,返回值的第一個字節都是負數,第二個字節可能是正數,也是合併的判斷依據

英文傳輸返回值:
[97, 98, 99, 100, 101, 102]    
對應:abcdef
中文傳輸返回值:
[-26, -79, -119, -27, -83, -105, -26, -117, -122, -27, -120, -122, -28, -68, -96, -24, -66, -109]         
對應:漢字拆分傳輸(UTF-8編碼表示字符最多佔三個字節)

一次讀取多個字節:public int read(byte[ ] b)

 public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("e:\\b.txt");

        byte[] by = new byte[1024];
        int len = 0;
        while((len = fis.read(by))!=-1){
            //避免讀出的數據不滿足數組大小
            System.out.print(new String(by,0,len));
        }

        fis.close();
    }

public int read(byte[ ] b):把讀取的數據存到數組b裏,返回值是實際讀取到的字節個數,如果緩衝區沒有了就返回-1

注意:  這裏by數組的長度一般是1024或者1024的整數倍
          相對於一個字節的讀取快了1024倍或者1024的整數倍,傳輸視頻等大文件時使用

傳輸圖片練習代碼

public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("D:\\圖片.jpeg");
        FileOutputStream fos = new FileOutputStream("E:\\copy.jpeg");

        byte[] by = new byte[1024];
        int len = 0;
        while((len = fis.read(by)) != -1){
            fos.write(by,0,len);
        }
        fos.close();
        fis.close();
    }

2.3 緩衝區類(高效類):BufferedOutputStream,BufferedInputStream

緩衝區類類似於一個杯子,用來裝水(水是指OutputStream,InputStream),運行效率高,代碼體現:

//向文件寫入數據
public static void main(String[] args) throws IOException {
        BufferedOutputStream bos = new BufferedOutputStream(new             
                                  FileOutputStream("e:\\b.txt"));

        bos.write("hello".getBytes());
        bos.close();
    }
//從文件讀取數據 
public static void main(String[] args) throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new 
                          FileInputStream("e:\\b.txt"));

        byte[] by = new byte[1024];
        int len = 0;
        while ((len = bis.read(by)) != -1){
            System.out.println(new String(by,0,len));
        }
        bis.close();
    }

3.轉換流的使用

3.1 可將字節流轉化爲字符流:OutputStreamWriter,InputStreamReader

由於用的是字符,有很多字符集,寫入和讀取的字符集要一致,不一致會亂碼。

//寫入數據
public static void main(String[] args) throws IOException {
        //使用指定字符集,把字節流轉換爲字符流
        OutputStreamWriter osw = new OutputStreamWriter(new 
                        FileOutputStream("e:\\b.txt"),"UTF-8");
        osw.write("漢字");
        //刷新一下,但流未關閉,還能寫入數據
        osw.flush();
        //先刷新,在關閉此流
        osw.close();
    }
//從文件讀出數據 
public static void main(String[] args) throws IOException {
        InputStreamReader isr = new InputStreamReader(new 
                        FileInputStream("e:\\b.txt"),"UTF-8");

        int len = 0;
        char[] by = new char[1024];
        while((len = isr.read(by)) != -1){
            System.out.print(new String(by,0,len));
        }
        isr.close();
    }

 flush和close的區別:在寫入字符時,字符是在緩衝區的,文件裏並沒有,此時flush一下後,就會進入文件。flush能寫入數據,但並沒有把流關閉,隨後還能寫入數據。而close是刷新寫入數據後把流關閉,隨後就不能寫入數據了。

3.2 OutputStreamWriter,InputStreamReader的封裝類:FileWriter,FileReader

利用封裝的類複製文件,代碼:

public static void main(String[] args) throws IOException{
        FileWriter osw = new FileWriter("e:\\b.txt");
        FileReader isr = new FileReader("e:\\a.txt");

        int len = 0;
        char[] chars = new char[1024];
        while ((len = isr.read(chars)) != -1){
            osw.write(chars,0,len);
            //osw.flush();
        }
        osw.close();
        isr.close();
    }

3.3 緩衝區類(高效類):BufferedWriter,BufferedReader

//寫入
public static void main(String[] args) throws IOException {
        BufferedWriter bw = new BufferedWriter(new FileWriter("e:\\b.txt"));

        bw.write("hello");
        bw.close();
    }
//讀出
public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("e:\\b.txt"));

        int len = 0;
        char[] c = new char[1024];
        while((len = br.read(c)) != -1){
            System.out.println(c);
        }
        br.close();
    }

這兩個類有特殊的方法:

public void newLine():系統決定換行符
public String readLine():一次讀取一行數據,沒有數據時返回null

方法的使用:

//複製文件練習 
public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("e:\\a.txt"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("e:\\b.txt"));

        String str = null;
        while((str = br.readLine()) != null){
            bw.write(str);
            bw.newLine();
        }
        bw.close();
        br.close();
    }

BufferReader的子類:LineNumberReader

其特有功能:

特殊方法: int getLineNumber() :獲取當前行號
          void setLineNumber(int lineNumber):設置當前行號

代碼:

public static void main(String[] args) throws IOException {
        LineNumberReader lnr = new LineNumberReader(new FileReader("e:\\b.txt"));
        lnr.setLineNumber(11);//從第12行開始
        String str = null;
        while((str = lnr.readLine()) != null){
            int line = lnr.getLineNumber();
            System.out.println(line +":"+str);
        }
    }

 運行結果:

12:hello
13:world
14:java

4.數據輸入輸出流 

DataOutputStream:FilterOutputStream的子類

數據輸入輸出流可以讀寫任意類型數據

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

    }

    private static void read() throws IOException {
        DataInputStream dis = new DataInputStream(new FileInputStream("e:\\b.txt"));

        int i = dis.readInt();
        char c = dis.readChar();
        float f = dis.readFloat();
        double d = dis.readDouble();

        dis.close();
        System.out.println(i);
        System.out.println(c);
        System.out.println(f);
        System.out.println(d);
    }

    private static void write() throws IOException{
        DataOutputStream dos = new DataOutputStream(new FileOutputStream("e:\\b.txt"));

        dos.writeInt(12);
        dos.writeChar('a');
        dos.writeFloat(12.32f);
        dos.writeDouble(14.36);

        dos.close();
    }

5.內存操作流

不需要文件,用於處理臨時存儲信息,程序結束,數據就從內存中消失,這個有讀有寫,對應的讀的操作類:

字節數組:java.io.InputStream 繼承者 java.io.ByteArrayInputStream

字符數組:java.io.Reader  繼承者 java.io.CharArrayReader

字符串:java.io.Reader 繼承者 java.io.StringReader

字節數組(三種類似)的寫入讀出操作:

 public static void main(String[] args) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        baos.write("hello".getBytes());
        baos.write("java".getBytes());
        //這個close()不起任何作用,內部源碼是個空的,主要是爲迎合父類操作
        //baos.close();
        byte[] by = baos.toByteArray();
        ByteArrayInputStream bios = new ByteArrayInputStream(by);
        int len = 0;
        while((len = bios.read()) != -1){
            System.out.print((char) len);
        }
        //這個close()也是
        bios.close();
    }

6.打印流

打印流讀字面意思就可以知道這個只有向文件寫數據,沒有讀數據:

字節打印流:java.io.FilterOutputStream 繼承者 java.io.PrintStream

字符打印流:java.io.Writer  繼承者 java.io.PrintWriter

特點:

1.只有寫數據,沒有讀數據,只能操作目的地,不能操作數據源

2.可以操作任意類型數據:print(),println()

3.如果啓用了自動刷新,能夠自動刷新

PrintWriter pw = new PrintWriter(new FileWriter("e:\\b.txt"),true);
啓用自動刷新,但必須使用println()(包含了寫入,換行,刷新)

4.該流可以直接操作文件

那些可直接操作文件的流:FileOutputStream,FileInputStream,FileWriter,FileReader,PrintStream,PrintWriter

代碼示例:

 public static void main(String[] args) throws IOException {
        PrintWriter pw = new PrintWriter(new FileWriter("e:\\b.txt"),true);

//        pw.print("hello");
//        pw.print(100);
//        pw.print("java");
        pw.println("hello");
        pw.println(100);
        pw.println("java");
//        pw.close();// 代碼中close()也會刷新,測試自動刷新,可以把close()註釋
    }

7.標準輸入輸出流

public static final InputStream in
public static final PrintStream out

標準輸出流:System.out 顯示器
標準輸入流:System.in  鍵盤

與我們常用的輸入輸出一樣,在輸出流中用打印流的方法都能使用 :public static final PrintStream out

 public static void main(String[] args) {
        PrintStream p = System.out;
        p.println(11);//與下面意思一樣
        System.out.println(12);
    }

8.隨機訪問流

此類不是一個流,是Object的子類
融合了InputStream和OutputStream
支持對文件隨機訪問讀取和寫入

 public static void main(String[] args) throws IOException {
        RandomAccessFile raf = new RandomAccessFile("E:\\b.txt","rw");//第二個參數是操作文件的模式,讀寫兩種寫法一樣

//        raf.writeInt(100);
//        raf.writeChar('a');
//        int i = raf.readInt();
//        System.out.println(i);
//        System.out.println("當前文件指針位置"+raf.getFilePointer());
        raf.seek(4);//設置指針位置
        char c = raf.readChar();
        System.out.println(c);
        System.out.println("當前文件指針位置"+raf.getFilePointer());
        raf.close();
    }

9.合併流

字面意思,一次同時讀取多個文件。只有讀操作

構造方法:SequenceInputStream(InputStream,InputStream):合併兩個文件

                  SequenceInputStream(Enumeration<? extends InputStream> e):合併多個文件

 把a.txt和b.txt的文件內容傳到c.txt,兩種方式:

    public static void main(String[] args) throws IOException {
        //合併兩個文件
//        InputStream is1 = new FileInputStream("e:\\a.txt");
//        InputStream is2 = new FileInputStream("e:\\b.txt");
//        SequenceInputStream sis = new SequenceInputStream(is1,is2);
        //合併多個文件
        Vector<InputStream> vi = new Vector<InputStream>();
        InputStream is1 = new FileInputStream("e:\\a.txt");
        InputStream is2 = new FileInputStream("e:\\b.txt");
        vi.add(is1);
        vi.add(is2);
        //利用構造方法:SequenceInputStream(Enumeration<? extends InputStream> e)
        Enumeration<InputStream> ei = vi.elements();//返回此向量的組件的枚舉。
        SequenceInputStream sis = new SequenceInputStream(ei);
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("e:\\c.txt"));
        int len = 0;
        byte[] by = new byte[1024];
        while ((len = sis.read(by)) != -1){
            bos.write(by,0,len);
        }
        bos.close();
        sis.close();
    }

10.序列化流反序列化流

序列化流(對像操作流):寫 ObjectOutputStream,對象--》流
                把對象按照流一樣的方式存入文本文件或者在網絡中傳輸
反序列化流:讀 ObjectInputStream,流--》對象
                把文本文件中的流對象或者網絡中的流對象數據還原爲對象

 public static void main(String[] args) throws IOException, ClassNotFoundException {
        write();
        read();
    }

    private static void read() throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("e:\\c.txt"));

        Object o = ois.readObject();
        System.out.println(o);
        ois.close();
    }

    private static void write() throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("e:\\c.txt"));
        Student s = new Student("張三",100,120,148);

        oos.writeObject(s);
        oos.close();
    }

 

/**
 * Serializable:序列化
 * 如果某個變量不想被序列化,可加入關鍵字transient
 */
public class Student implements Serializable {
    //姓名
    public String name;
    //語文成績
    public int chinese;
    //數學成績
    public int math;
    //英語成績
    public int english;
    ......
}

11.Properties

屬性集合類,是一個可以和IO流相結合使用的集合類。可以保存在流中或者從流中加載。屬性列表中每一個鍵所對應的值都是字符串。

java.util.Hashtable<Object,Object>

               繼承者 java.util.Properties

特有功能 

bject setProperty(String key, String value):調用 Hashtable 的方法 put。

String getProperty(String key) :用指定的鍵在此屬性列表中搜索屬性。

Set<String> stringPropertyNames() : 返回此屬性列表中的鍵集,其中該鍵及其對應值是字符串,如果在主屬性列表中未找到同名的鍵,則還包括默認屬性列表中不同的鍵。

 文件與此類的結合:

方法: void load(Reader reader) 按簡單的面向行的格式從輸入字符流中讀取屬性列表(鍵和元素對)。

            void store(Writer writer, String comments) 以適合使用 load(Reader) 方法的格式,將此 Properties 表中的屬性列表(鍵和元素對)寫入輸出字符。

使用代碼:

 public static void main(String[] args) throws IOException {
        myLoad();
        myStore();
    }

    private static void myStore() throws IOException{
        Properties p = new Properties();
        Writer w = new FileWriter("e:\\c.txt");

        p.setProperty("張飛","丈八蛇矛");
        p.setProperty("呂布","方天畫戟");
        p.setProperty("劉備","雙股劍");

        p.store(w,"hero");
        w.close();
    }

    private static void myLoad() throws IOException{
        Properties p = new Properties();
        Reader r = new FileReader("e:\\c.txt");

        p.load(r);
        System.out.println(p);
        r.close();
    }

 

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