使用緩沖Buffered流復制文件時,文件大小不一樣的問題


  在用java批量復制文件時,用的是帶緩沖區的字符流,結果復制后的文件比原來的文件要大,代碼如下:

  

public static void main(String[] args) throws IOException {
    
        File file = new File("D:\\aaa\\原文件.PDF");
        String fileName = "D:\\aaa\\復制的文件";
        
        for(int i=0;i < 10; i++){
    
//            FileUtils.copyFile(file, new File(fileName + i + ".PDF"));
    
            BufferedReader reader = new BufferedReader(new FileReader(file));
            BufferedWriter writer = new BufferedWriter(new FileWriter(new File(fileName + i + ".PDF")));
            String  data = null;
            while((data = reader.readLine()) != null){
                writer.write(data);
                writer.newLine();
                writer.flush();
            }
            writer.close();
            reader.close();
    
//            BufferedInputStream input = new BufferedInputStream(new FileInputStream(file));
//            BufferedOutputStream output = new BufferedOutputStream(
//                    new FileOutputStream(new File(fileName + i + ".PDF")));
//
//            int len = -1;
//            byte[] data = new byte [1024];//一次讀取1M
//            while ((len = input.read(data)) != -1){
//                output.write(data,0,len);
//            }
//
//            output.close();
//            input.close();
            System.out.println("復制了第:" + i + " 個文件");
        }
    
        System.out.println("復制完成!");
    }

復制后的效果如下圖:

 

 

   可以發現,復制后的文件大小和原文件是不一樣的,這里是因為我復制的是PDF文件,而不是普通的文本文件,所以這里不能使用字符流BufferedReader,而應該使用字節流inputStream

下面總結一下字節流與字符流的區別與各自的使用場景:

  • Java 中的字節流處理的最基本單位為 1 個字節,通常用來處理二進制數據。字節流類 InputStream 和 OutputStream 類均為抽象類,代表了基本的輸入字節流和輸出字節流。
  • Java 中的字符流處理的最基本的單元是 Unicode 代碼單元(大小2字節),通常用來處理文本數據。

區別:

  • 字節流操作的基本單元是字節;字符流操作的基本單元是字符
  • 字節流默認不使用緩沖區;字符流使用緩沖區
  • 字節流通常用於處理二進制數據,不支持直接讀寫字符;字符流通常用於處理文本數據
  • 在讀寫文件需要對文本內容進行處理:按行處理、比較特定字符的時候一般會選擇字符流;僅僅讀寫文件,不處理內容,一般選擇字節流

 

特征:

  • 以 stream 結尾都是字節流,reader 和 writer 結尾是字符流
  • InputStream 是所有字節輸入流的父類,OutputStream 是所有字節輸出流的父類
  • Reader 是字符輸入流的父類,Writer 是字符輸出流的父類

 

常見的字節流:

  • 文件流:FileOutputStream 和 FileInputStream
  • 緩沖流:BufferedOutputStream 和 BufferedInputStream
  • 對象流:ObjectOutputStream 和 ObjectInputStream

 

常見的字符流:

  • 字節轉字符流:InputStreamReader 和 OutputStreamWriter
  • 緩沖字符流:PrintWriter 和 BufferedReader

 

可以這樣理解文件復制的過程:
  字符流:二進制數據 --編碼-> 字符編碼表 --解碼-> 二進制數據
  字節流:二進制數據 —> 二進制數據

  所以問題就是出現在編碼和解碼的過程中,既然是字符的編碼表,那它就是包含所有的字符,但是字符的數量是有限的,這就意味着它不能表示一些超過編碼表的字符,因為根本不存在表中。所以,JVM 會使用一些字符進行替換,基本上都是亂碼(所以大小會發生變化),而且如果有一個數據恰好是-1,那么讀取就會中斷,引起數據丟失。

 


免責聲明!

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



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