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));
}
}
}