IO/拷貝文件的四種方法/解決亂碼

IO概述

分類

IO流根據傳輸方向分爲兩種:輸入流(讀),輸出流(寫)
根據單位:字節流(java.io.InputStream,java.io.OutputStream),字符流(java.io.Reader,java.io.Writer)
InputStream和OutputStream
上面是InputStream,下面是OutputStream
σ_›σ 原諒我從百度隨便摳的圖☝☝☝

字節流(文本,圖片,音頻,視頻)

在JDK中提供兩個抽象類InputStream,OutputStream作爲字節流的頂級父類。可以把InputStream,OutputStream比作兩根水管。
InputStream輸入管道,源設備—>程序
OutputStream輸出管道,程序—>目標設備
最後一定要關閉管道!!避免浪費資源!!
下面是最完整的寫法:

OutputStream out = null;
    try {
            out = new FileOutputStream(file);
            out.write(content.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {//finally一定會執行,所以在這裏關流
            try {
                if (out != null)
                    out.close();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                out = null;//交付給gc
            }
        }

拷貝文件

public void copy_Paste(String srcPath,String destPath) throws Exception{

        FileInputStream fis = new FileInputStream(srcPath);
        FileOutputStream fos = new FileOutputStream(destPath);

下面提供4種方法進行拷貝

        /**1.一個個字節:效率低**/
        int data1 = fis.read();

        while(data1!=-1){
            fos.write((char)data1);
            data1 = fis.read();
        }
/**2.用一個數組作爲緩衝**/
byte[] buff = new byte[1024];
        int total = fis.read(buff);
        while(total!=-1){
            fos.write(buff);
            total = fis.read(buff);
        }
    /**3.緩衝流**/
        BufferedInputStream bis = new BufferedInputStream(fis);
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        int data2 = bis.read();
        while(data2!=-1){
            bos.write(data2);
            data2 = bis.read();
/**4.數據輸入輸出流**/
 DataInputStream dis = new DataInputStream(fis);//包裝了fis
        DataOutputStream dos = new DataOutputStream(fos);
        int d = dis.readInt();
        dos.writeInt(d);
        while(dis.available()>0){
            d = dis.readInt();
            dos.writeInt(d);

        //關流 先關輸入再關輸出,不然水管會爆。。
        dis.close();
        dos.close();
        //由於DataInputStream,DataOutputStream是包裝流
        //所以下面兩行可以不用寫
        fis.close();
        fos.close();

字符流(文本文件)

參考上面第四點

標準輸入輸出流

在System類中定義了三個常量:in,out,err,它們被習慣性地稱爲標準輸入輸出流

常量 類型 作用
in InputStream 標準輸入流 默認用於讀取鍵盤輸入的數據
out PrintStream 標準輸出流 默認將數據輸出到命令行窗口
err PrintStream 標準錯誤流 與out類似,通常輸出的是應用程序運行時的錯誤信息

File類

File類用於封裝一個路徑

public void copy_Paste(String srcPath,String destPath) {
  copy_Paste(new  File(srcPath),new  File(destPath));
}

亂碼問題

產生原因

字符=字節+編碼

字節是計算機信息技術用於計量存儲容量的一種計量單位,因此字節流也稱爲萬能流 而編碼方式不同,可能導致字符和字節的換算方式不同,可能1字符=2字節,也可能1字符=3字節


編碼是將數據轉化爲二進制的過程,解碼則是編碼的逆過程 因此,亂碼問題都出現在解碼過程中


注意:下圖字符集中只有GBK可以對漢字進行編碼(以GB開頭的編碼方式都包含中文字符)

這裏寫圖片描述

再比如:”中文”二字的GBK的字節流爲d6 d0 ce c4,如果用utf-8(不支持中文)去解碼,勢必會亂碼。

解決方法

  • 指定read,write編碼

InputStreamReader(InputStream in, CharsetDecoder dec)
創建使用給定字符集解碼器的 InputStreamReader。

OutputStreamWriter(OutputStream out, CharsetEncoder enc)
創建使用給定字符集編碼器的 OutputStreamWriter。


  • 重新編碼,怎麼來怎麼回

String(byte[] bytes, Charset charset)
通過使用指定的 charset 解碼指定的 byte 數組,構造一個新的 String。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章