1. 程式人生 > >20.Java語言IO流、IO流異常處理、以及Properties

20.Java語言IO流、IO流異常處理、以及Properties

IO流

I :Input(輸入)資料從外部流入程式(硬碟到記憶體)

O:Output(輸出)資料從程式流出外部(記憶體到硬碟)

流:類似於水流—有方向,線性

作用:

可以讀寫檔案的內容

體系:

A).位元組流:按位元組讀寫檔案。可以操作任何型別檔案

           1).輸出流:OutputStream(抽象類)

                      |--FileOutputStream(子類)

           2).輸入流:InputStream(抽象類)

                     |--FileInputStream(子類)

B).字元流:按“

字元讀寫檔案。僅僅可以讀、寫純文字檔案。

           1).輸出流:Writer(抽象類)

                     |--OutputStreamWriter(轉換流)

                         |--FileWriter(子類)

           2).輸入流:Reader(抽象類)

                     |--InputStreamReader(轉換流)

                         |--FileReader(子類)

IO流圖解:

位元組流

一切皆為位元組,“位元組流”是Java中IO流的最基本的流,任何的其它流(字元流、列印流....)都是基於位元組流的

1位元組輸出流OutputStream:

OutputStream(抽象類) à 子類:FileOutputStream

      輸出的方法;

      1).write(int b)            輸出一個位元組

      2).write(byte[] byteArray)       輸出一個位元組陣列

      3).write(byte[] byteArray,int off,int len)輸出一個位元組陣列的部分,起始位置和長度

2位元組輸出流子類FileOutputStream:

       構造方法:

       1). FileOutputStream​(String name) :使用指定的檔名構造一個輸出流 覆蓋寫

       2). FileOutputStream​(File file) 建立檔案輸出流以寫入由指定的 File物件表示的檔案。覆蓋寫

       3). FileOutputStream​(File file, boolean append) 建立檔案輸出流以寫入由指定的 File物件表示的檔案。追加寫

       4). FileOutputStream​(String name, boolean append) 建立檔案輸出流以指定的名稱寫入檔案。 追加寫

       輸出的方法:(無特有,都是從父類繼承的)

       1).write(int b):輸出一個位元組(很少用)

       2).write(byte[] byteArray):輸出一個位元組陣列(常用:write("你好".getBytes()))

       3).write(byte[] byteArray,int off,int len):輸出一個位元組陣列的一部分(很少用)。

       注意:

              1).Java中任何的輸出流,構造時檔案都可以不存在,會自動建立一個空檔案

              2).Java的IO流不要構造在一個“存在的目錄上”,否則執行時異常。

              3).三種輸出的方法都是無返回值的,每次呼叫方法都會寫入一次內容

public static void main(String[] args) throws IOException {
    File file = new File("demo.txt");
    FileOutputStream out1 = new FileOutputStream(file);
    FileOutputStream out2 = new FileOutputStream(file,true);
    FileOutputStream out3 = new                    FileOutputStream("demo.txt");
    FileOutputStream out4 = new FileOutputStream("demo.txt",true);
    int b = 97;
    byte[] array = new byte[4];
    out1.write(b);
    out1.write(array);
    out1.write(array,0,3);
    String s = "我愛Java";
    out1.write(s.getBytes(),0,3);//一個漢字是三個位元組
}

寫出換行

Windows系統裡,換行符號是 \r\n

fos.write("\r\n".getBytes());

3位元組輸入流InputStream:

       InputStream(抽象類) à 子類: FileInputStream

       讀取的方法:

       1).public int read():依次讀取一個位元組;

       2).public int read(byte[] byteArray):依次讀取一個位元組陣列;

       3).public int read(byte[] byteArray,int off,int len)讀取一個位元組陣列的部分,起始位置和長度

4.位元組輸入流的子類FileInputStream:

       構造方法:

       1).FileInputStream(String pathname):

       2).FileInputStream(File file):

//構造方法

File file = new File("demo.txt");

FileInputStream in1 = new FileInputStream(file);

FileInputStream in2 = new FileInputStream("demo.txt");

       注意:

       1).Java中所有的“輸入流”構造時,檔案必須存在,否則執行時異常。

       讀取的方法(從父類繼承):

       1).public int read():讀取一個位元組;返回讀取的位元組對應編碼,兩次呼叫會連續讀取兩個位元組

       2).public int read(byte[] byteArray):讀取一個位元組陣列;返回每次讀取的位元組個數,讀取的位元組覆蓋陣列原有的內容,如果讀取一個返回1覆蓋陣列第一個內容,如果沒有讀取到內容返回-1

3).write(byte[] byteArray,int off,int len)輸出一個位元組陣列的部分,起始位置和長度返回讀取的位元組數

byte[] b = new byte[4];
System.out.println(in1.read());
System.out.println(in1.read());
in1.read(b,0,3);
while ((a = in1.read(b)) != -1) {
    System.out.println(Arrays.toString(b));
}

//結果
// 97
//98
//[99, 100, 101, 102]
//[103, 100, 101, 102]

5.位元組流檔案複製案例:

       首先按照位元組流讀入檔案,然後按照位元組流輸出檔案,所以需要一個輸入流一個輸出流

       示例程式碼:

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

    //首先讀取檔案,建立輸入流
    FileInputStream in = new FileInputStream("demo.txt");

    //然後寫入檔案,建立輸出流
    FileOutputStream out = new    FileOutputStream("demo_copy.txt");

    //1,一個位元組的讀取,一個位元組的寫入
    int b = 0;
    while ((b = in.read()) != -1) {
        out.write(b);
    }

    //2.一個位元組陣列的輸入和輸出
    byte[] byteArray = new byte[3];
    while ((b = in.read(byteArray)) != -1) {
        //最後一次輸入的位元組個數不一定
        //所以輸出用部分輸出的方式
        out.write(byteArray,0,b);
    }
    in.close();
    out.close();
}

字元流

按照一次一個字元讀取和寫入,因為每個國家的字元的位元組數不同,如果按照一個位元組的方式比較麻煩,所以Java提供了只能操作純文字字元流的方式,

1.字元輸出流Writer:

       Writer(抽象類) à OutputStreamWriter(轉換流) à FileWriter(子類)

       輸出的方法:

       1).write(int c):輸出一個字元;

       2).write(char[] chArray):輸出一個字元陣列

       3).write(char[] chArray,int off,int len):輸出字元陣列的一部分;

       4).write(String s):輸出一個字串;

       5).write(String s,int off,int len):輸出字串的一部分。

2.字元輸出流子類FileWriter:

       構造方法:

       1).FileWriter​(String fileName) 構造一個給定檔名的FileWriter物件。

       2).FileWriter​(File file) 給一個File物件構造一個FileWriter物件。 

       3).FileWriter​(String fileName, boolean append) 構造一個給定帶有布林值的和檔名FileWriter物件。表示是否追加寫入的資料。

4).FileWriter​(File file, boolean append) 給一個File物件和布林值構造一個FileWriter物件。  表示是否追加寫入的資料。

       輸出的方法(全部從父類繼承):

1).write(int c):輸出一個字元;

       2).write(char[] chArray):輸出一個字元陣列

       3).write(char[] chArray,int off,int len):輸出字元陣列的一部分;

       4).write(String s):輸出一個字串;

       5).write(String s,int off,int len):輸出字串的一部分。

       注意:

       1).字元流輸出完之後必須重新整理或者關閉,關閉有重新整理的功能,否則內容在快取區不會被寫入檔案

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

    //構造方法:
    File file = new File("demo.txt");
    FileWriter out1 = new FileWriter(file);
    FileWriter out2 = new FileWriter(file,true);
    FileWriter out3 = new FileWriter("demo.txt",true);
    FileWriter out4 = new FileWriter("demo.txt");

    //輸出方法:
    char[] array = {'a','b','c'};
    out1.write(97);
    out1.write(array);
    out1.write(array,0,2);
    out1.write("java");
    out1.write("java",0,3);

    //關閉重新整理
    out1.close();

}

關閉和重新整理:

因為內建緩衝區的原因,如果不關閉輸出流,無法寫出字元到檔案中。但是關閉的流物件,是無法繼續寫出資料的。

如果我們既想寫出資料,又想繼續使用流,就需要 flush 方法了。

flush() :重新整理緩衝區,流物件可以繼續使用。

close() :關閉流,釋放系統資源。關閉前會重新整理緩衝區。

字元輸入流Reader:

Reader(抽象類) à InputStreamWriter(轉換流) à FileReader(子類)

       讀取的方法:

       1).int read():讀取一個字元。返回:讀取的字元的編碼值;int型別

       2).int read(char[] chArray):讀取一個字元陣列;返回值:讀取的字元數量。

字元輸入流子類FileReader:

       構造方法:

       1).FileReader(String path):

       2).FileReader(File file):

       輸入的方法:

       1).public int read():依次讀取一個位元組;

       2).public int read(byte[] byteArray):依次讀取一個位元組陣列;

3).public int read(byte[] byteArray,int off,int len)讀取一個位元組陣列的部分,起始位置和長度

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

    //構造方法
    File file = new File("demo.txt");
    FileReader in1 = new FileReader(file);
    FileReader in2 = new FileReader("demo.txt");

    //讀取方法
    char[] arr = new char[4];
    in1.read();
    in1.read(arr);
    in1.read(arr, 0, 2);
}

IO異常處理

JDK7之前,使用 try...catch...finally程式碼塊處理異常部分

JDK7,使用try-with-resource處理,自動關閉每個資源

JDK9,對於引入物件的方式,支援的更加簡潔,也是自動關閉資源

Properties

       java.util.Properties(類):此類是一個Map集合。此類中有兩個方法可以用於方便的讀、寫配置檔案;

配置檔案

指軟體執行過程中記錄使用者的一些設定資訊的檔案,這種配置檔案在國際上有一個通用的格式:

                     名1 = 值

                     名2 = 值

                     名3 = 值

                     ....

這種格式同Map的鍵值對格式正好匹配,所以Java製作了一個Properties類來方便的讀寫配置檔案。

使用:

       1).Properties集合-->配置檔案:store()方法

       2).配置檔案-->Properties集合:load()方法

程式碼示例:

public class Properties_新增到檔案 {

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

        FileWriter out = new FileWriter("demo.txt");
        Properties ps = new Properties();
        ps.setProperty("姓名1", "姓名11");
        ps.setProperty("姓名2", "姓名22");
        ps.setProperty("姓名3", "姓名33");
        ps.store(out,"名單");
        out.close();
    }
}
public class Properties_讀取檔案內容 {

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

        Properties ps = new Properties();
        FileReader in = new FileReader("demo.txt");
        ps.load(in);
        //stringPropertyNames()返回Set<String>集合
        for (String s : ps.stringPropertyNames()) {
            System.out.println(ps.get(s));
        }
    }
}