java進階(33)–IO流

一、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類
//www.cnblogs.com/mrwhite2020/p/14322392.html

九、對象流
//www.cnblogs.com/mrwhite2020/p/14322446.html

十、IO和Properties
//www.cnblogs.com/mrwhite2020/p/14322463.html

 ——————————————分割線,以下為正文————————————————-

一、IO流概念:

1、基本概念

I:Input

O:Output

通過IO可以完成硬盤文件的讀和寫。

2、IO流分類

(1)按照流的方向分類:

輸入流(Input)或者稱為讀(Reader)

輸出流(Output)或者稱為寫(Write)

(2)按照讀取數據方式不同分類:

位元組流:按照位元組方式讀取數據,一次讀取1個位元組byte,等同一個8個二進制位,這種流是萬能的,什麼類型的文件都可以讀取,包括:文本文件、圖片、視頻、聲音等

字符流:按照字符方式讀取數據,一次讀取一個字符,這種流是為了方便讀取普通文件而存在,這種流不能讀取圖片、聲音、視頻、word等,只能讀取純文本文件。

假設文件test.txt 內容為:”h世界”

位元組流讀取:第一次讀’h’(佔用一個位元組),第二次讀’世’字符的一半(佔用一個位元組)

字符流讀取:第一次讀’h’(佔用一個位元組),第二次讀’世’字符(佔用一個字符)

3、java.io流的四大家族

(1)java.io.InputStream位元組輸入流

(2)java.io.OutputStream位元組輸出流

(3)java.io.Reader字符輸入流

(4)java.io.Writer字符輸出流

在java中以Stream結尾都是位元組流,以Reader/Writer結尾都是字符流

 4、流的close和flush方法

(1)close()

所有的流都實現java.io.closeble接口,都是可以關閉的,都右close方法。

流是一個管理,是內存與硬盤之間的通道,用完之後一定要關閉,不然會耗費很多資源,養成好習慣,用完流一定要關閉。

(2)flush()

所有的輸出流都實現了java.io.Flushable接口,都可以刷新,都包含flush方法。

養成好習慣,輸出流輸出玩都需要flush刷新一下,表示將通道/管道當中的剩餘未輸出的數據強行輸出完,即清空管道,沒有使用flush方法會導致數據丟失

5、java.io下常用的16個流

(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;

 

二、FileInputStream位元組輸入流

1、FileInputStream完成位元組流輸入的流程

(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數組讀取

 4、FileInputStream的available

(1)查看剩餘的位元組數

 (2)available的作用:可以不適用while循環,直接一次讀取全部的位元組,但是不適合大的文件,因為byte數組不能太大

5、FileInputStream的skip方法

 

三、FileOutputStream位元組輸出流

1、FileOutputStream概念:

位元組輸出流,從內存到硬盤

2、FileOutputStream輸出流程

(1)使用byte數組+write方法+flush方法寫入

 (2)檢查文件結果,相對路徑為項目根目錄下:

(3)再次執行,會將原文件中內容覆蓋,依然輸出:abcdab 

(4)修改構造方法,true代表文本的追加

  (5)查看相對路徑下的文本執行結果:文本追加了內容

 3、改進FileInputStream+String輸出

(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 }

查看文件輸出結果

 \

 

四、FileReader與FileWrite

1、FileReader概念

文件字符輸入流,只能讀取普通文本,讀取文本內容時比較方便、快捷

2、舉例FileReader

 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 }

檢查源文件與讀取的內容

 3、FileWrite概念:

文件字符輸出流,只能輸出普通文本

4、舉例FileWrite:

 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 }

查看複製後結果

 

五、帶有緩衝區的字符流

1、BufferedReader概念:

帶有緩衝區的字符輸入流,使用此流不需要自定義char數組,或者說不需要自定義byte數組,自帶緩衝區。

2、舉例說明BufferedReader:

(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 }

查看執行結果

3、節點流與包裝流

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

查看運行結果:

 4、BufferedWrite:帶有緩衝區的字符輸出流

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

查看執行結果:

 

六、數據流

1、DataOutputStream概念:

數據專屬的流

這個流可以將數據連同數據的類型一併寫入文件

 注意:這個文件不同普通文本文檔(這個文件使用記事本打不開)

2、舉例說明:DataOutputStream

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流打開,並且讀的順序需要與寫的順序一致。

 3、DataInputStream流概念:

數據位元組輸入流,DataOutputStream流寫的文件只能使用DataInputStream打開,並且讀的順序需要和寫的順序一致。

4、舉例說明: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、PrintStream標準位元組輸出流:

標準位元組輸出流,默認輸出到控制台。

 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 }

2、更改標準輸出流的輸出方向

 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 }

查看項目根目錄的輸出文件

  3、日誌工具生成原理:

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類

File類參照如下章節:

//www.cnblogs.com/mrwhite2020/p/14322392.html

 

九、對象流

對象流、序列化與反序列化參考如下章節:

//www.cnblogs.com/mrwhite2020/p/14322446.html

 

十、IO和Properties

IO和Properties聯合使用參考如下章節:

//www.cnblogs.com/mrwhite2020/p/14322463.html