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