一、IO流概念:
1、基本概念
2、IO流分類
3、java.io流的四大家族
4、流的close和flush方法
5、java.id下常用的16個流
二、FileInputStream位元組輸入流
1、FileInputStream完成位元組流輸入的流程
2、使用while優化FileInputStream讀取流程
3、FileInputStream最終版,使用byte陣列讀取
4、FileInputStream的available
5、FileInputStream的skip方法
三、FileOutputStream位元組輸出流
1、FileOutputStream概念
2、FileOutputStream輸出流程
3、改進FileInputStream+String輸出
4、檔案複製(FileInputStream+FileOutputStream)
四、FileReader與FileWrite
1、FileReader概念
2、舉例FileReader
3、FileWrite概念:
4、舉例FileWrite:
5、複製普通檔案(FileReader與FileWrite):
五、帶有緩衝區的字元流
1、BufferedReader概念:
2、舉例說明BufferedReader:
3、節點流與包裝流
4、BufferedWrite:帶有緩衝區的字元輸出流
六、資料流
1、DataOutputStream概念
2、舉例說明:DataOutputStream
3、DataInputStream流概念:
4、舉例說明:DataInputStream
七、標準輸出流
1、PrintStream標準位元組輸出流:
2、更改標準輸出流的輸出方向
3、日誌工具生成原理:
八、File類
https://www.cnblogs.com/mrwhite2020/p/14322392.html
九、物件流
https://www.cnblogs.com/mrwhite2020/p/14322446.html
十、IO和Properties
https://www.cnblogs.com/mrwhite2020/p/14322463.html
------------------------------------------分割線,以下為正文-------------------------------------------------
I:Input
O:Output
通過IO可以完成硬碟檔案的讀和寫。
(1)按照流的方向分類:
輸入流(Input)或者稱為讀(Reader)
輸出流(Output)或者稱為寫(Write)
(2)按照讀取資料方式不同分類:
位元組流:按照位元組方式讀取資料,一次讀取1個位元組byte,等同一個8個二進位制位,這種流是萬能的,什麼型別的檔案都可以讀取,包括:文字檔案、圖片、視訊、聲音等
字元流:按照字元方式讀取資料,一次讀取一個字元,這種流是為了方便讀取普通檔案而存在,這種流不能讀取圖片、聲音、視訊、word等,只能讀取純文字檔案。
假設檔案test.txt 內容為:"h世界"
位元組流讀取:第一次讀'h'(佔用一個位元組),第二次讀'世'字元的一半(佔用一個位元組)
字元流讀取:第一次讀'h'(佔用一個位元組),第二次讀'世'字元(佔用一個字元)
(1)java.io.InputStream位元組輸入流
(2)java.io.OutputStream位元組輸出流
(3)java.io.Reader字元輸入流
(4)java.io.Writer字元輸出流
在java中以Stream結尾都是位元組流,以Reader/Writer結尾都是字元流
(1)close()
所有的流都實現java.io.closeble介面,都是可以關閉的,都右close方法。
流是一個管理,是記憶體與硬碟之間的通道,用完之後一定要關閉,不然會耗費很多資源,養成好習慣,用完流一定要關閉。
(2)flush()
所有的輸出流都實現了java.io.Flushable介面,都可以重新整理,都包含flush方法。
養成好習慣,輸出流輸出玩都需要flush重新整理一下,表示將通道/管道當中的剩餘未輸出的資料強行輸出完,即清空管道,沒有使用flush方法會導致資料丟失
(1)檔案專屬:
java.io.FileInputStream;
java.io.FileOutputStream;
java.io.FileReader;
java.io.FileWriter;
(2)轉換流:位元組流轉為字元流
java.io.InputStream;
java.io.OutputStream;
(3)緩衝區專屬:
java.io.BufferedInputStream;
java.io.BufferedOutputStream;
java.io.BufferedReader;
java.io.BufferedWriter;
(4)資料專屬:
java.io.DataInputStream;
java.io.DataOutputStream;
(5)標準輸出流:
java.io.PrintStream;
java.io.PrintWriter;
(6)物件專屬:
java.io.ObjectInputStream;
java.io.ObjectOutputStream;
(1)準備檔案如下:
(2)建立位元組流輸入物件,Idea自動將路徑變斜槓
(3)alt+回車新增try+catch或者上報異常,這裡選擇try+catch
(4)第二種檔案路徑編寫方式"\"與"//"等價
(5)增加finally語句且初始化流放在try+catch語句外,並新增流的關閉,流關閉前需要增加流的判空ifn可預設生成 if(fis==null)
(6)增加流的讀取,並新增try+catch使用alt+回車,這裡建議選擇第一種異常
第一種:增加catch使用細粒度的異常
第二種:方法宣告異常
第三種:替換外層FIleNotFount為IO異常
第四種:內層在增加try+catch
(7)檢視列印結果為a對應的字元ascII碼值97
(8)可重複讀取6次,最後一次讀取不到返回-1
2、使用while優化FileInputStream讀取流程
3、FileInputStream最終版,使用byte陣列讀取
(1)檢視剩餘的位元組數
(2)available的作用:可以不適用while迴圈,直接一次讀取全部的位元組,但是不適合大的檔案,因為byte陣列不能太大
位元組輸出流,從記憶體到硬碟
(1)使用byte陣列+write方法+flush方法寫入
(2)檢查檔案結果,相對路徑為專案根目錄下:
(3)再次執行,會將原檔案中內容覆蓋,依然輸出:abcdab
(4)修改構造方法,true代表文字的追加
(5)檢視相對路徑下的文字執行結果:文字追加了內容
(1)使用String轉byte陣列輸出
(2)檢視輸出結果,追加一段String字串
4、檔案複製(FileInputStream+FileOutputStream)
(1)流程:拷貝過程是一邊讀、一邊寫;檔案型別任意,是萬能的
(2)舉例檔案複製:
1 package JAVAADVANCE;
2
3 import java.io.FileInputStream;
4 import java.io.FileNotFoundException;
5 import java.io.FileOutputStream;
6 import java.io.IOException;
7
8 public class TestAdvance33IOTest08 {
9 public static void main(String[] args) {
10 FileInputStream fis=null;
11 FileOutputStream fos=null;
12 try {
13 //建立一個輸入物件流
14 fis=new FileInputStream("D:\\javaTest\\inFile\\甜蜜家園第01集.mp4");
15 //建立一個輸出物件流
16 fos=new FileOutputStream("D:\\javaTest\\outFile\\甜蜜家園第01集.mp4");
17 //準備一個byte陣列,1024byte=1KB,*1024=1M,一次最多讀1M
18 byte[] bytes=new byte[1024*1024];
19 int readCount=0;
20 while ((readCount=fis.read(bytes))!=-1)
21 {
22 //讀取多少,寫多少
23 fos.write(bytes,0,readCount);
24 }
25 fos.flush();
26 } catch (FileNotFoundException e) {
27 e.printStackTrace();
28 } catch (IOException e) {
29 e.printStackTrace();
30 } finally {
31 //fos與fis的關閉分開try catch比較好,避免互相影響,有流沒有關閉
32 if (fos != null) {
33 try {
34 fos.close();
35 } catch (IOException e) {
36 e.printStackTrace();
37 }
38 }
39 if(fis!=null){
40 try {
41 fis.close();
42 } catch (IOException e) {
43 e.printStackTrace();
44 }
45 }
46 }
47
48
49
50
51 }
52 }
檢視檔案輸出結果
\
檔案字元輸入流,只能讀取普通文字,讀取文字內容時比較方便、快捷
1 package JAVAADVANCE;
2 import java.io.*;
3 public class TestAdvance33IOTest09FileReader {
4 public static void main(String[] args) {
5 FileReader reader= null;
6 try {
7 //建立字元輸入流
8 reader=new FileReader("C:\\Users\\Mr.White\\IdeaProjects\\javaAdvance\\myTestFile01");
9 //開始讀,使用char陣列,一次讀取4個字元
10 char[] chars=new char[4];
11 int readCount=0;
12 while ((readCount=reader.read(chars))!=-1){
13 System.out.println(new String(chars,0,readCount));
14 }
15 } catch (FileNotFoundException e) {
16 e.printStackTrace();
17 } catch (IOException e) {
18 e.printStackTrace();
19 } finally {
20 if (reader != null) {
21 try {
22 reader.close();
23 } catch (IOException e) {
24 e.printStackTrace();
25 }
26 }
27 }
28 }
29 }
檢查原始檔與讀取的內容
檔案字元輸出流,只能輸出普通文字
1 package JAVAADVANCE;
2 import java.io.FileWriter;
3 import java.io.IOException;
4 public class TestAdvance33IOTest10FileWrite {
5 public static void main(String[] args) {
6 FileWriter out = null;
7 try {
8 //建立字元輸出流物件,true使用追加寫入模式,否則重新執行會覆蓋
9 out=new FileWriter("fileWriteTest01",true);
10 //開始寫,使用char陣列
11 char[] chars={'我','是','中','國','人'};
12 //寫入全部char陣列
13 out.write(chars);
14 //再寫入部分char陣列,第3個字元開始,3個字元
15 out.write(chars,2,3);
16 //直接寫入String
17 out.write("我是個JAVA工程師");
18 out.flush();
19 } catch (IOException e) {
20 e.printStackTrace();
21 }finally {
22 if (out != null) {
23 try {
24 out.close();
25 } catch (IOException e) {
26 e.printStackTrace();
27 }
28 }
29 }
30 }
31 }
檢視輸出結果,相對路徑為工程根目錄下
5、複製普通檔案(FileReader與FileWrite):
(1)使用FileReader與FileWrite進行拷貝,只能拷貝普通文字檔案
(2)舉例複製普通檔案:
1 package JAVAADVANCE;
2 import java.io.FileNotFoundException;
3 import java.io.FileReader;
4 import java.io.FileWriter;
5 import java.io.IOException;
6 public class TestAdvance33IOTest11NormalFileCopy {
7 public static void main(String[] args) {
8 FileReader in =null;
9 FileWriter out = null;
10 try {
11 //建立字元輸入流
12 in=new FileReader("D:\\javaTest\\inFile\\fileWriteTest01");
13 //建立字元輸出流
14 out=new FileWriter("D:\\javaTest\\outFile\\fileWriteTest01");
15 //一邊讀一邊寫
16 char[] chars=new char[1024*512]; //一次讀取1M檔案
17 int readCount=0;
18 while ((readCount=in.read(chars))!=-1){
19 out.write(new String(chars,0,readCount));
20 }
21 //寫完後重新整理
22 out.flush();
23 } catch (FileNotFoundException e) {
24 e.printStackTrace();
25 } catch (IOException e) {
26 e.printStackTrace();
27 } finally {
28 if (in != null) {
29 try {
30 in.close();
31 } catch (IOException e) {
32 e.printStackTrace();
33 }
34 }
35 if (out != null) {
36 try {
37 out.close();
38 } catch (IOException e) {
39 e.printStackTrace();
40 }
41 }
42 }
43 }
44 }
檢視複製後結果
帶有緩衝區的字元輸入流,使用此流不需要自定義char陣列,或者說不需要自定義byte陣列,自帶緩衝區。
(1)準備檔案
(2)按照行讀取檔案
package JAVAADVANCE;
import java.io.*;
public class TestAdvance33IOTest12BufferedReader {
//異常先丟擲
public static void main(String[] args) throws IOException {
FileReader reader=new FileReader("D:\\javaTest\\inFile\\fileWriteTest02");
//FileReader為節點流,BufferedReader為包裝流/處理流
BufferedReader br=new BufferedReader(reader);
//讀第一行
String firstLine = br.readLine();
System.out.println(firstLine);
//讀第二行
String secondLine = br.readLine();
System.out.println(secondLine);
//讀第三行
String thirdLine = br.readLine();
System.out.println(thirdLine);
//只需要關閉最外層的流,對於包裝流來說
br.close();
}
}
(3)迴圈讀取全部檔案
1 package JAVAADVANCE;
2 import java.io.BufferedReader;
3 import java.io.FileReader;
4 import java.io.IOException;
5 public class TestAdvance33IOTest12BufferedReader02 {
6 //異常先丟擲
7 public static void main(String[] args) throws IOException {
8 FileReader reader=new FileReader("D:\\javaTest\\inFile\\fileWriteTest02");
9 //FileReader為節點流,BufferedReader為包裝流/處理流
10 BufferedReader br=new BufferedReader(reader);
11 //使用String字串讀取
12 String s=null;
13 while ((s=br.readLine())!=null){
14 System.out.println(s);
15 }
16 //只需要關閉最外層的流,對於包裝流來說
17 br.close();
18 }
19 }
檢查執行結果
(4)print方法測試readLine方法不帶換行符
1 package JAVAADVANCE;
2 import java.io.BufferedReader;
3 import java.io.FileReader;
4 import java.io.IOException;
5 public class TestAdvance33IOTest12BufferedReader02 {
6 //異常先丟擲
7 public static void main(String[] args) throws IOException {
8 FileReader reader=new FileReader("D:\\javaTest\\inFile\\fileWriteTest02");
9 //FileReader為節點流,BufferedReader為包裝流/處理流
10 BufferedReader br=new BufferedReader(reader);
11 //使用String字串讀取
12 String s=null;
13 while ((s=br.readLine())!=null){
14 //print方法測試readLine方法不帶換行符
15 System.out.print(s);
16 }
17 //只需要關閉最外層的流,對於包裝流來說
18 br.close();
19 }
20 }
檢視執行結果
(1)節點流與包裝流都是相對而言
(2)舉例說明:節點流與包裝流
以下例子:
in與reader:in為節點流,reader為包裝流
reader與br:reader與節點流,br為包裝流
package JAVAADVANCE;
import java.io.*;
public class TestAdvance33IOTest12BufferedReader03 {
//異常先丟擲
public static void main(String[] args) throws IOException {
FileInputStream in=new FileInputStream("D:\\javaTest\\inFile\\fileWriteTest02");
//通過InputStreamReader轉換流將位元組流轉換為字元流
InputStreamReader reader=new InputStreamReader(in);
BufferedReader br =new BufferedReader(reader);
//使用String字串讀取
String line=null;
while ((line=br.readLine())!=null){
//print方法測試readLine方法不帶換行符
System.out.println(line);
}
//只需要關閉最外層的流,對於包裝流來說
br.close();
}
}
檢視執行結果:
(1)舉例說明BufferedWrite
package JAVAADVANCE;
import java.io.*;
public class TestAdvance33IOTest13BufferedWrite {
//異常先丟擲
public static void main(String[] args) throws IOException {
BufferedWriter out=new BufferedWriter(new FileWriter("D:\\javaTest\\outFile\\fileWriteTest02"));
out.write("hello world");
out.write("\nhello kitty");
out.flush();
out.close();
}
}
檢視執行結果
(2)使用包裝流追加輸出
package JAVAADVANCE;
import java.io.*;
public class TestAdvance33IOTest13BufferedWrite02 {
//異常先丟擲
public static void main(String[] args) throws IOException {
BufferedWriter out=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("D:\\javaTest\\outFile\\fileWriteTest02",true)));
out.write("\n這是繼續使用包裝流追加的文字");
out.flush();
out.close();
}
}
檢視執行結果:
資料專屬的流
這個流可以將資料連同資料的型別一併寫入檔案
注意:這個檔案不同普通文字文件(這個檔案使用記事本打不開)
package JAVAADVANCE;
import java.io.*;
public class TestAdvance33IOTest14DataOutputStream01 {
//異常先丟擲
public static void main(String[] args) throws IOException {
//建立資料專屬位元組輸出流
DataOutputStream dos=new DataOutputStream(new FileOutputStream("D:\\javaTest\\outFile\\fileWriteTest03"));
byte b=100;
short s=200;
int i=300;
float t=400F;
double d=3.14;
boolean sex=false;
char c='a';
dos.writeByte(b);
dos.writeShort(s);
dos.writeInt(i);
dos.writeFloat(t);
dos.writeDouble(d);
dos.writeBoolean(sex);
dos.writeChar(c);
dos.flush();
dos.close();
}
}
檢視檔案結果:無法使用記事本或notepad++開啟,需要使用DataInputStream流開啟,並且讀的順序需要與寫的順序一致。
資料位元組輸入流,DataOutputStream流寫的檔案只能使用DataInputStream開啟,並且讀的順序需要和寫的順序一致。
1 package JAVAADVANCE;
2 import java.io.*;
3 public class TestAdvance33IOTest15DataInputStream01 {
4 //異常先丟擲
5 public static void main(String[] args) throws IOException {
6 //建立資料專屬位元組輸入流
7 DataInputStream dis =new DataInputStream(new FileInputStream("D:\\javaTest\\outFile\\fileWriteTest03"));
8 //開始讀,讀的順序要與寫的時候保持一致。
9 byte b= dis.readByte();
10 short s=dis.readShort();
11 int i=dis.readInt();
12 float t =dis.readFloat();
13 double d=dis.readDouble();
14 boolean sex=dis.readBoolean();
15 char c=dis.readChar();
16 dis.close();
17 System.out.println(b);
18 System.out.println(s);
19 System.out.println(i);
20 System.out.println(t);
21 System.out.println(d);
22 System.out.println(sex);
23 System.out.println(c);
24
25 }
26 }
檢視顯示結果
標準位元組輸出流,預設輸出到控制檯。
1 package JAVAADVANCE;
2 import java.io.IOException;
3 import java.io.PrintStream;
4 public class TestAdvance33IOTest16PrintStream01 {
5 //異常先丟擲
6 public static void main(String[] args) throws IOException {
7 //標準輸出流直接輸出到控制檯
8 System.out.println("hello world");
9 //換一種寫法
10 PrintStream ps=System.out;
11 ps.println("hello zhangsan");
12 ps.println("hello lisi");
13 //標準輸出流不需要手動關閉
14 }
15 }
1 package JAVAADVANCE;
2 import java.io.FileOutputStream;
3 import java.io.IOException;
4 import java.io.PrintStream;
5 public class TestAdvance33IOTest16PrintStream01 {
6 //異常先丟擲
7 public static void main(String[] args) throws IOException {
8 //更改標準輸出流的輸出方向,指向log檔案
9 System.setOut(new PrintStream(new FileOutputStream("log")));
10 //再次輸出
11 System.out.println("hello world");
12 System.out.println("hello kitty");
13 }
14 }
檢視專案根目錄的輸出檔案
package JAVAADVANCE;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.Date;
public class TestAdvance33IOTest16LogTest {
//異常先丟擲
public static void log(String msg) {
try {
PrintStream out=new PrintStream(new FileOutputStream("log.txt",true));
//改變檔案的輸出方向
System.setOut(out);
//當前日期格式
Date nowTime = new Date();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
String strTime=sdf.format(nowTime);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
編寫測試程式開始測試日誌列印
1 package JAVAADVANCE;
2 public class TestAdvance33IOTest16LogTest {
3 public static void main(String[] args) {
4 //測試工具是否好用
5 TestAdvance33IOTest16PrintStream02.log("呼叫了Sytem的gc()方法,建議啟動垃圾回收");
6 TestAdvance33IOTest16PrintStream02.log("呼叫了userService的dosome()方法");
7 TestAdvance33IOTest16PrintStream02.log("使用者正在嘗試登入,驗證失敗");
8 }
9 }
檢視輸出結果
File類參照如下章節:
https://www.cnblogs.com/mrwhite2020/p/14322392.html
物件流、序列化與反序列化參考如下章節:
https://www.cnblogs.com/mrwhite2020/p/14322446.html
IO和Properties聯合使用參考如下章節:
https://www.cnblogs.com/mrwhite2020/p/14322463.html