java 讀取文件流


 

搬運自速學堂:https://www.sxt.cn/Java_jQuery_in_action/ten-iqtechnology.html

JAVA中IO流體系:

 

四大IO抽象類

·InputStream

      此抽象類是表示字節輸入流的所有類的父類。InputSteam是一個抽象類,它不可以實例化。 數據的讀取需要由它的子類來實現。根據節點的不同,它派生了不同的節點流子類 。

      繼承自InputSteam的流都是用於向程序中輸入數據,且數據的單位為字節(8 bit)。

      常用方法:

      int read():讀取一個字節的數據,並將字節的值作為int類型返回(0-255之間的一個值)。如果未讀出字節則返回-1(返回值為-1表示讀取結束)。

      void close():關閉輸入流對象,釋放相關系統資源。

· OutputStream

      此抽象類是表示字節輸出流的所有類的父類。輸出流接收輸出字節並將這些字節發送到某個目的地。

      常用方法:

      void write(int n):向目的地中寫入一個字節。

      void close():關閉輸出流對象,釋放相關系統資源。

· Reader

      Reader用於讀取的字符流抽象類,數據單位為字符。

      int read(): 讀取一個字符的數據,並將字符的值作為int類型返回(0-65535之間的一個值,即Unicode值)。如果未讀出字符則返回-1(返回值為-1表示讀取結束)。

      void close() : 關閉流對象,釋放相關系統資源。

· Writer

      Writer用於寫入的字符流抽象類,數據單位為字符。

      void write(int n): 向輸出流中寫入一個字符。

      void close() : 關閉輸出流對象,釋放相關系統資源

一、文件字節流

FileInputStream通過字節的方式讀取文件,適合讀取所有類型的文件(圖像、視頻、文本文件等)。Java也提供了FileReader專門讀取文本文件。

FileOutputStream 通過字節的方式寫數據到文件中,適合所有類型的文件。Java也提供了FileWriter專門寫入文本文件。

讀取:

import java.io.*;
public class TestIO2 {
    public static void main(String[] args) {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream("d:/a.txt"); // 內容是:abc
            StringBuilder sb = new StringBuilder();
            int temp = 0;
            //當temp等於-1時,表示已經到了文件結尾,停止讀取
            while ((temp = fis.read()) != -1) {
                sb.append((char) temp);
            }
            System.out.println(sb);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                //這種寫法,保證了即使遇到異常情況,也會關閉流對象。
                if (fis != null) {
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

 寫入:

import java.io.FileOutputStream;
import java.io.IOException;
public class TestFileOutputStream {
    public static void main(String[] args) {
        FileOutputStream fos = null;
        String string = "北京尚學堂歡迎您!";
        try {
            // true表示內容會追加到文件末尾;false表示重寫整個文件內容。
            fos = new FileOutputStream("d:/a.txt", true);
            //該方法是直接將一個字節數組寫入文件中; 而write(int n)是寫入一個字節
            fos.write(string.getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (fos != null) {
                    fos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

void write(byte[ ] b),該方法不再一個字節一個字節地寫入,而是直接寫入一個字節數組;另外其還有一個重載的方法:void write(byte[ ] b, int off, int length),這個方法也是寫入一個字節數組,但是我們程序員可以指定從字節數組的哪個位置開始寫入,寫入的長度是多少。

利用文件流實現文件的復制

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class TestFileCopy {
    public static void main(String[] args) {
        //將a.txt內容拷貝到b.txt
        copyFile("d:/a.txt", "d:/b.txt"); 
    }
 
    /**
     * 將src文件的內容拷貝到dec文件
     * @param src 源文件
     * @param dec 目標文件
     */
    static void copyFile(String src, String dec) {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        //為了提高效率,設置緩存數組!(讀取的字節數據會暫存放到該字節數組中)
        byte[] buffer = new byte[1024];
        int temp = 0;
        try {
            fis = new FileInputStream(src);
            fos = new FileOutputStream(dec);
            //邊讀邊寫
            //temp指的是本次讀取的真實長度,temp等於-1時表示讀取結束
            while ((temp = fis.read(buffer)) != -1) {
                /*將緩存數組中的數據寫入文件中,注意:寫入的是讀取的真實長度;
                 *如果使用fos.write(buffer)方法,那么寫入的長度將會是1024,即緩存
                 *數組的長度*/
                fos.write(buffer, 0, temp);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //兩個流需要分別關閉
            try {
                if (fos != null) {
                    fos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (fis != null) {
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

注意

      在使用文件字節流時,我們需要注意以下兩點:

      1. 為了減少對硬盤的讀寫次數,提高效率,通常設置緩存數組。相應地,讀取時使用的方法為:read(byte[] b);寫入時的方法為:write(byte[ ] b, int off, int length)。

      2. 程序中如果遇到多個流,每個流都要單獨關閉,防止其中一個流出現異常后導致其他流無法關閉的情況。

二、文件字符流

前面介紹的文件字節流可以處理所有的文件,但是字節流不能很好的處理Unicode字符,經常會出現“亂碼”現象。所以,我們處理文本文件,一般可以使用文件字符流,它以字符為單位進行操作。

使用FileReader與FileWriter實現文本文件的復制

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class TestFileCopy2 {
    public static void main(String[] args) {
        // 寫法和使用Stream基本一樣。只不過,讀取時是讀取的字符。
        FileReader fr = null;
        FileWriter fw = null;
        int len = 0;
        try {
            fr = new FileReader("d:/a.txt");
            fw = new FileWriter("d:/d.txt");
            //為了提高效率,創建緩沖用的字符數組
            char[] buffer = new char[1024];
            //邊讀邊寫
            while ((len = fr.read(buffer)) != -1) {
                fw.write(buffer, 0, len);
            }
 
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fw != null) {
                    fw.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (fr != null) {
                    fr.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

三、緩沖字節流

Java緩沖流本身並不具有IO流的讀取與寫入功能,只是在別的流(節點流或其他處理流)上加上緩沖功能提高效率,就像是把別的流包裝起來一樣,因此緩沖流是一種處理流(包裝流)。

當對文件或者其他數據源進行頻繁的讀寫操作時,效率比較低,這時如果使用緩沖流就能夠更高效的讀寫信息。因為緩沖流是先將數據緩存起來,然后當緩存區存滿后或者手動刷新時再一次性的讀取到程序或寫入目的地。

因此,緩沖流還是很重要的,我們在IO操作時記得加上緩沖流來提升性能。

BufferedInputStream和BufferedOutputStream這兩個流是緩沖字節流,通過內部緩存數組來提高操作流的效率。

下面我們通過兩種方式(普通文件字節流與緩沖文件字節流)實現一個視頻文件的復制,來體會一下緩沖流的好處。

使用緩沖流實現文件的高效率復制

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
 
public class TestBufferedFileCopy1 {
 
    public static void main(String[] args) {
        // 使用緩沖字節流實現復制
        long time1 = System.currentTimeMillis();
        copyFile1("D:/電影/華語/大陸/尚學堂傳奇.mp4", "D:/電影/華語/大陸/尚學堂越
                 "+"來越傳奇.mp4");
        long time2 = System.currentTimeMillis();
        System.out.println("緩沖字節流花費的時間為:" + (time2 - time1));
 
        // 使用普通字節流實現復制
        long time3 = System.currentTimeMillis();
        copyFile2("D:/電影/華語/大陸/尚學堂傳奇.mp4", "D:/電影/華語/大陸/尚學堂越
                 "+"來越傳奇2.mp4");
        long time4 = System.currentTimeMillis();
        System.out.println("普通字節流花費的時間為:" + (time4 - time3));
    }
    /**緩沖字節流實現的文件復制的方法*/
    static void copyFile1(String src, String dec) {
        FileInputStream fis = null;
        BufferedInputStream bis = null;
        FileOutputStream fos = null;
        BufferedOutputStream bos = null;
        int temp = 0;
        try {
            fis = new FileInputStream(src);
            fos = new FileOutputStream(dec);
            //使用緩沖字節流包裝文件字節流,增加緩沖功能,提高效率
            //緩存區的大小(緩存數組的長度)默認是8192,也可以自己指定大小
            bis = new BufferedInputStream(fis);
            bos = new BufferedOutputStream(fos);
            while ((temp = bis.read()) != -1) {
                bos.write(temp);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //注意:增加處理流后,注意流的關閉順序!“后開的先關閉!”
            try {
                if (bos != null) {
                    bos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (bis != null) {
                    bis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (fos != null) {
                    fos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (fis != null) {
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /**普通節流實現的文件復制的方法*/
    static void copyFile2(String src, String dec) {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        int temp = 0;
        try {
            fis = new FileInputStream(src);
            fos = new FileOutputStream(dec);
            while ((temp = fis.read()) != -1) {
                fos.write(temp);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (fos != null) {
                    fos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (fis != null) {
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

執行結果如圖:

注意

      1. 在關閉流時,應該先關閉最外層的包裝流,即“后開的先關閉”。

      2. 緩存區的大小默認是8192字節,也可以使用其它的構造方法自己指定大小。

四、緩沖字符流

BufferedReader/BufferedWriter增加了緩存機制,大大提高了讀寫文本文件的效率,同時,提供了更方便的按行讀取的方法:readLine(); 處理文本時,我們一般可以使用緩沖字符流。

使用BufferedReader與BufferedWriter實現文本文件的復制

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
 
public class TestBufferedFileCopy2 {
    public static void main(String[] args) {
        // 注:處理文本文件時,實際開發中可以用如下寫法,簡單高效!!
        FileReader fr = null;
        FileWriter fw = null;
        BufferedReader br = null;
        BufferedWriter bw = null;
        String tempString = "";
        try {
            fr = new FileReader("d:/a.txt");
            fw = new FileWriter("d:/d.txt");
            //使用緩沖字符流進行包裝
            br = new BufferedReader(fr);
            bw = new BufferedWriter(fw);
            //BufferedReader提供了更方便的readLine()方法,直接按行讀取文本
            //br.readLine()方法的返回值是一個字符串對象,即文本中的一行內容
            while ((tempString = br.readLine()) != null) {
                //將讀取的一行字符串寫入文件中
                bw.write(tempString);
                //下次寫入之前先換行,否則會在上一行后邊繼續追加,而不是另起一行
                bw.newLine();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (bw != null) {
                    bw.close();
                }
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            try {
                if (br != null) {
                    br.close();
                }
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            try {
                if (fw != null) {
                    fw.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (fr != null) {
                    fr.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

注意

      1. readLine()方法是BufferedReader特有的方法,可以對文本文件進行更加方便的讀取操作。

      2. 寫入一行后要記得使用newLine()方法換行。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM