1. 程式人生 > >Java IO流總結

Java IO流總結

依次 自帶 file類 文件夾 二進制文件 緩沖 rri 操作 .class

說在前面的話:IO流是用來操作File的,因此先說一下File

一、File類:文件和目錄路徑名的抽象表示。

File 類只能操作文件的屬性,文件的內容是不能操作的。

1.作用:用於對磁盤文件操作。刪除、創建等。

2.三種構造函數:

①直接傳入一個路徑,拿到一個文件或者文件夾

File file1 = new File("F:\\test");

②第一個參數傳入父路徑、第二個參數傳入子路徑或者文件

File file2 = new File("F:\\test", "test.txt");

③第一個參數傳入file文件、第二個參數傳入子路徑或者文件

File file3 = new File(file1, "test.txt");

3.路徑的表示:

文件夾的分割可以使用"/",通常用在Linux系統,windows也可以用

"\\"通常用在Windows系統,註意‘\‘需要進行轉義

4.需要註意的幾個常用方法

①:.delete() 刪除文件 刪除成功true 刪除失敗false;若刪除文件夾,此文件夾不能有子內容

②:createNewFile() 創建一個新文件創建失敗返回false 需要指定的新文件名由調用他的文件對象來決定,而不是傳參數,沒有才能創建成功需要捕獲異常

③:mkdir:只能創建一層目錄,如果倒數第二層目錄也不存在,創建失敗;mkdirs:可以創建多層目錄,無論有幾層不存在都可以依次創建

④:list()返回當前目錄中的所有文件和文件夾的名字,返回值類型為String[]

String[] list = file1.list();
for (String string : list) {
    System.out.println(string);
}

可以再參數中傳入FilenameFilter接口的實現類對象,表示對列表中的所有文件進行遍歷過濾
需要重寫accept方法,如果保留當前文件return true,如果不要當前文件return false

String[] list1 = file1.list(new FilenameFilter()) {
    @Override
    public boolean accept(File dir, String name) {
    
// dir:表示包含當前文件夾的父路徑     // name:表示當前文件名      if (name.endsWith(".txt")) {      return true;      }else {      return false;     }     } }); for (String string1 : list1) { System.out.println(string1); }

⑤:返回當前目錄中的所有文件和文件夾的路徑,返回值類型為File[]

File[] files = file1.listFiles();
for (File file : files) {
    System.out.println(file+"----"+file.getName());
}

同樣可以對文件進行過濾
①與list()一樣使用 FilenameFilter()進行過濾
②使用FileFilter接口的實現類進行過濾

File[] files1 = file1.listFiles(new FileFilter() {
        @Override
        public boolean accept(File pathname) {
        // TODO Auto-generated method stub
                if (pathname.getName().endsWith(".txt")) {
            return true;
          }else {
            return false;
          }
    }
});
for (File fileN : files1) {
    System.out.println(fileN+"----"+fileN.getName());
}    

二、IO流的分類:

1.根據流的方向:輸入流和輸出流

2.根據讀取文字的大小:字節流和字符流(字節流按照字節讀取,讀取中文時容易亂碼;字符流按照字符讀取,通常用於讀取中文

3.根據讀取的方式:節點流和緩存流

三、字節流java.io.InputStream java,io,OutputStream

1.FileInputStream類

①該流繼承於InputStream用於從文件讀取數據,它的對象可以用關鍵字 new 來創建。
②構造方法
可以使用字符串類型的文件名來創建一個輸入流對象來讀取文件:
FileInputStream f = new FileInputStream("C:/java/hello");
也可以使用一個文件對象來創建一個輸入流對象來讀取文件。我們首先得使用 File() 方法來創建一個文件對象:
File f = new File("C:/java/hello");
FileInputStream out = new FileInputStream(f);
③常用方法
available():返回下一次對此輸入流調用的方法可以不受阻塞地從此輸入流讀取的字節數。返回一個整數值。
read(int r):這個方法從 InputStream 對象讀取指定字節的數據。返回為整數值。返回下一字節數據,如果已經到結尾則返回-1。
read(byte[] b): 從此輸入流中將最多 b.length 個字節的數據讀入一個 byte 數組中
close():關閉此文件輸入流並釋放與此流有關的所有系統資源。拋出IOException異常

2.FileOutStream

①該類用來創建一個文件並向文件中寫數據。
如果該流在打開文件進行輸出前,目標文件不存在,那麽該流會創建該文件。
②構造方法
使用字符串類型的文件名來創建一個輸出流對象:
OutputStream f = new FileOutputStream("C:/java/hello");
也可以使用一個文件對象來創建一個輸出流來寫文件。我們首先得使用File()方法來創建一個文件對象:
File f = new File("C:/java/hello");
OutputStream f = new FileOutputStream(f);
③常用方法
write(int b): 將指定字節寫入此文件輸出流。
write(byte[] b): 將 b.length 個字節從指定 byte 數組寫入此文件輸出流中。

3、BufferedInputStream、BufferedOutputStream

繼承自FilterInputStream、FilterOutputStream

1.作用:在基本流的基礎上進行包裝,讀取或者寫入文件時,將通過緩存進行。
即,先將內容寫入到緩存區,緩存區滿以後再進行讀取或寫入操作
可以大大減小文件的操作次數,提高寫入效率
2.緩存流的使用:
在基礎流的基礎上進行包裝:
new BufferedInputStream(new FileInputStream("F:\\test\\test.txt"));
這種寫法我們稱為IO鏈,IO關閉時需要關閉最外層流,內層流將自動關閉
3.使用BufferedOutStream,在關閉時通常調用flush()方法;
表示關閉前將緩存區刷新,將緩存區剩余未滿的內容寫入文件;
實際上close()方法自帶刷新,這樣做是一種習慣。

4.DataInputStream和DataOutputStream

1. 分別繼承自FilterInputStream和FilterOutStream
2.特殊:
①采用二進制對文件進行讀寫操作
②與基本流相比,可以直接讀寫Java中的基本數據類型

3.另外如果操作的一個文件是一個二進制文件,需要使用DataInputStream替代FileInputStream
不代替也可以讀)同樣,Data系列的流也有read和write方法與基本流操作相同

4.用Data流寫入的文件,只能用Data流讀,不能使用基本流讀

5.與基本流相比幾個特有方法
readUTF():首先讀取兩個字節,以 String 的形式返回此字符串
readInt():讀取四個輸入字節並返回一個 int 值
readDouble():讀取八個輸入字節並返回一個 double 值。
6.上面的方法,如果此流在讀取所有字節之前到達末尾,則會拋出
java.io.EOFException異常;EOF:END OF FILE
https://www.cnblogs.com/yiwangzhibujian/p/7107084.html(詳細解釋了為啥會拋異常)

自己領會的解決方法 :

public class Demo04_DataINOUTStream2 {
    public static void main(String[] args) {
        DataInputStream dis = null;
        FileInputStream fis = null;
        try {
            fis = new FileInputStream("F:\\test\\Demo02_IO.class");
            if (fis.available() != 0) {
                dis = new DataInputStream(fis);
            }else {
                System.out.println("文件已沒有可讀內容!");
            }
        try {
            while (true) {
                    System.out.println(dis.readInt());
            }} catch (EOFException e) {
                System.out.println("一定會拋出這條異常,表示目標文件已讀完,沒有可以讀的內容了,我們不做任何處理就好了!");
            }
        
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            try {
                dis.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}


第一篇:
https://www.cnblogs.com/ouhaitao/p/7683568.html

 1     ObjectInputStream ois = null;
 2     FileInputStream fis=new FileInputStream(filePath);
 3     //當文件中的有內容時
 4     if(fis.available()!=0)
 5         ois = new ObjectInputStream(fis);
 6     else{
 7         System.out.println("文件為空!");
 8         return ;
 9     }
10     try{
11         while(true)                            
12           System.out.println((Student)ois.readObject());
13     }catch(EOFException e){
14     }

原理就是:先用基本流判斷文件是不是還有可讀內容,只有在判斷有可讀內容是才實例化一個
高級流對象,這事再去讀,當讀完又會報錯這時只需手動在read...()方法捕捉一下EOFExceptiion這個異常,不處理就好了。

第二篇:
https://blog.csdn.net/ouyang_peng/article/details/46448877

5.ObjectInputStream/ObjectOutputStream

1.繼承java.io.InputStream和java.io.OutputStream
2.與基本流相同,可以直接使用read write 方法
3.可以使用Data流的方法
4.特殊方法:readObject()和writeObject()
對象的序列化和反序列化
1.對象的序列化:將程序中的對象,持久化的保存在文件中的過程ObjectOutStream
2.對象的反序列化:將文件中保存的對象,重新讀取到程序中的過程。ObjectInputStream
如果要對實體類對象進行序列化,實體類需要實現Serializable(可序列化)接口,
添加一個序列化版本號private static final long serialVersionUID = 4992258028211704199L;
若果不添加序列化版本號,當序列化一個對象後,如果實體類屬性有增刪,再進行反序列化時會造成錯誤
java.io.InvalidClassException,因為系統認為這已經不是同一個類

註意雖然叫對象的序列化,但是使用這readObject()和writeObject()這兩個方法可以直接傳入一個對象集合

readObject()和writeObject()方法也存在EOFException這個異常,解決辦法同
DataInputStream和DataOutputStream中的readInt()等方法
http://note.youdao.com/noteshare?id=506c27323c6b8a0b6cf3d1f7f97639eb&sub=C87F25CC0E7342558556C89380D7E2AF

四、字符流

1.Reader、Writer

1.在處理數據單元時,以一個字符作為單位,而字節流是以一個字節作為單位
2.字符的基類:Reader、Writer(抽象類)
FileReader、FileWrite是直接繼承自抽象類的兩個字符基本流
3、FileReader、FileWrite在讀寫文件的時候,只能使用系統默認編碼格式;
無法指定編碼,如果文件格式與系統默認格式不一致,那使用這兩個方法讀寫將造成中文亂碼
4.雖然算不上緩存流,但是不 flush()會導致寫不進去,讀不出來

2.InputStreamReader、OutputStreamWriter

1.將字節流轉為字符流,同時支持自定義讀寫的編碼格式
2.常見的編碼格式
ASCLL:美國標準消息碼;
ISO8859-1:西歐洲碼;
ANSI編碼,可以分為很多種:
簡體中文:GB2312、GBK
繁體中文:big-5
日文中文...
Unicode編碼:國際標準碼,兼容絕大多數國家的編碼格式
可以分為:UTF-6、UTF-8、UTF-16

下面兩行把一個utf-8格式的字符串先分解成一個字符數組b,然後使用new String(b,"GBK")生成一個新的GBK格式的字符串s1
String s = "中國fdhasfdj";
byte[] b = s.getBytes("UTF-8");
String s1 = new String(b,"GBK");

3.BufferedReader、BufferedWriter

BufferedWriter 和 BufferedReader 為帶有默認緩沖的字符輸出輸入流,因為有緩沖區所以效率比沒有緩沖區的很高。

1、BufferedWriter 類
構造方法:bufferedWriter bf = new bufferedWriter(Writer out );

主要方法:void write(char ch);//寫入單個字符。

void write(char []cbuf,int off,int len)//寫入字符數據的某一部分。

void write(String s,int off,int len)//寫入字符串的某一部分。

void newLine()//寫入一個行分隔符。

void flush();//刷新該流中的緩沖。將緩沖數據寫到目的文件中去。

void close();//關閉此流,再關閉前會先刷新他。

2、BufferedReader類。
構造方法:BufferedReader br = new BufferReader(Reader in);

主要方法:int read();//讀取單個字符。

int read(char[] cbuf,int off,int len);//將字符讀入到數組的某一部分。返回讀取的字符數。達到尾部 ,返回-1。

String readLine(); //讀取一個文本行。

void close(); //關閉該流。並釋放與該流相關的所有資源。

Java IO流總結