簡單文件讀寫的工具類(使用字節流工具類實現)

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;

/**
 * 簡單文件讀寫的工具類(使用字節流工具類實現)
 */
public class SimpleFileRwUtil {

    /*
        關於文件讀寫的一點理解
        =================================================================================================
        1. 讀取內容到內存中,是否會亂碼和文件的編碼格式無關。只和內容的編碼格式有關。
            若是寫入的內容編碼格式是GBK,讀取時卻使用UTF-8進行解碼,則會出現亂碼。
            文件的編碼格式是GBK也好,UTF-8也好,都不會影響。
            文件的編碼格式只會影響文本內容在文件中的顯示。若是文件的編碼格式內容的編碼格式不一致,則打開文件時會出現亂碼。
            
        2. 獲取字符串的字節流byte[]        (字節流:是UNICODE編碼的字符串,以指定編碼格式(如UTF-8)編碼後,形式的byte數組)
            String.getBytes()            
                // 做業內容:將內存中以UNICODE編碼的字符串轉成某種固定的編碼格式(CHARSET)的字節流。
                // CHARSET使用文件的默認編碼格式。若是當前文件的編碼格式是UTF-8,就使用UTF-8編碼格式。若是當前文件格式是GBK,就使用GBK格式編碼格式。
                // 若是文件的默認編碼格式不被支持,則使用"ISO-8859-1"編碼格式進行編碼。
               String.getBytes(CHARSET)
                   // 做業內容:將內存中以UNICODE編碼的字符串轉成某種固定的編碼格式(CHARSET)的字節流。
        
        3. 文件的編碼格式?
            文件自己也是有編碼格式的,文件的編碼格式相似於一個標記,指定文件在被打開時,文件以什麼編碼格式去解碼文件裏的字節流,以顯示正確的內容。
            
            查看TXT文件的編碼格式:
                     |- 以windows自帶的NotePad打開文件;
                     |- 點擊"文件(F)"父菜單下的"另存爲(A)"子菜單;
                     |- 在彈出框的最下方,能夠看到當前文件使用的編碼格式,多是 ANSI(即GBK)或 UTF-8;
     */

    // 讀取文件流時,一次性讀取的最大字節數
    public final static int buffer_size = 5120;

    /**
     * 以指定編碼格式解碼從文件中讀取的字節流
     * 
     * @param filePath        要操做的文件路徑
     * @param charsetName    指定編碼格式
     * @return
     */
    public static String readStringFromFile(String filePath, String charsetName) throws Exception {
        File file = new File(filePath);
        return SimpleFileRwUtil.readStringFromFile(file, charsetName);
    }

    /**
     * 以指定編碼格式解碼從文件中讀取的字節流
     * 
     * @param file            要操做的文件
     * @param charsetName    指定編碼格式
     * @return
     */
    public static String readStringFromFile(File file, String charsetName) throws Exception {
        // 從文件中讀取字節流
        byte[] resullt = SimpleFileRwUtil.readBytesFromFile(file);

        // 若是未指定編碼格式,使用java文件默認的編碼格式進行解碼
        if (null == charsetName) {
            return new String(resullt);
        }
        // 若是指定了編碼格式,使用指定的編碼格式進行解碼
        else {
            return new String(resullt, charsetName);
        }
    }

    /**
     * 從文件中讀取字節流(有編碼格式)
     * 
     * @param file    要操做的文件
     * @return
     */
    public static byte[] readBytesFromFile(File file) throws Exception {
        // 文件不存在時,拋出異常
        if (null == file) {
            throw new Exception("parameter file is null.");
        }
        if (!file.exists()) {
            throw new FileNotFoundException(String.format("file (%s) is not exist.", file.getAbsolutePath()));
        }

        // 讀取文件流
        BufferedInputStream in = null;
        byte[] result = new byte[0];
        try {
            // 實例化輸入流
            FileInputStream fis = new FileInputStream(file);
            in = new BufferedInputStream(fis);

            // 一次讀取的字節最大長度
            byte[] buffer = new byte[buffer_size];

            int count = 0;
            while ((count = in.read(buffer)) != -1) {
                // 拷貝buffer中的前count個元素到result中
                result = SimpleFileRwUtil.appendByteArray(result, buffer, count);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            SimpleFileRwUtil.close(in);
        }

        // 返回讀取的字節流
        return result;
    }

    /**
     * 追加src的前count個元素到result尾部
     * 
     * @param desc
     * @param src
     * @param count
     * @return
     */
    public static byte[] appendByteArray(byte[] desc, byte[] src, int count) {
        // 特殊狀況1
        if (null == src) {
            return desc;
        }

        // 特殊狀況2,此時append不爲null
        if (null == desc) {
            byte[] result = new byte[count];
            // count值大於src的長度時會報數組越界的異常,此處不處理
            System.arraycopy(src, 0, result, 0, count);
            return result;
        }

        // 原結果數組長度
        int orignalLength = desc.length;

        // 結果數組擴容
        int newLength = orignalLength + count;
        desc = Arrays.copyOf(desc, newLength);

        // 數組追加
        System.arraycopy(src, 0, desc, orignalLength, count);

        // 返回追加後的完整數組
        return desc;
    }

    /**
     * 將String字符串以指定編碼格式寫入文件
     * 
     * @param filePath            要操做的文件路徑
     * @param content            要寫入的字符串
     * @param charsetName        指定的編碼格式
     * @param append            內容是追加仍是覆蓋
     */
    public static void writeStringToFile(String filePath, String content, String charsetName, boolean append) {
        File file = new File(filePath);
        SimpleFileRwUtil.writeStringToFile(file, content, charsetName, append);
    }

    /**
     * 將String字符串以指定編碼格式寫入文件
     * 
     * @param file                要操做的文件
     * @param content            要寫入的字符串
     * @param charsetName        指定的編碼格式
     * @param append            內容是追加仍是覆蓋
     */
    public static void writeStringToFile(File file, String content, String charsetName, boolean append) {
        try {
            // 要寫入的內容爲空,直接返回
            if (null == content) {
                return;
            }

            byte[] bytes;
            // 若是沒指定編碼格式,使用java文件的默認編碼格式
            if (null == charsetName) {
                bytes = content.getBytes();
            }
            // 若是指定了編碼格式,使用指定的編碼格式進行編碼
            else {
                bytes = content.getBytes(charsetName);
            }

            // 寫入文件流到文件
            SimpleFileRwUtil.writeBytesToFile(file, bytes, append);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

    /**
     * 將byte[]流寫入文件
     * 
     * @param file        要操做的文件
     * @param bytes        字節流是有編碼格式的
     * @param append    內容是追加仍是覆蓋
     */
    public static void writeBytesToFile(File file, byte[] bytes, boolean append) {
        BufferedOutputStream out = null;
        try {
            // 若是文件目錄不存在,建立目錄
            if (!file.getParentFile().exists()) {
                file.mkdirs();
            }

            // 實例化輸出流
            FileOutputStream fos = new FileOutputStream(file, append);
            out = new BufferedOutputStream(fos);

            // 輸出內容到文件
            if (null != bytes) {
                out.write(bytes);
            }

            // 清空緩衝區
            out.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            SimpleFileRwUtil.close(out);
        }
    }

    /**
     * 關閉流
     * 
     * @param in
     * @param out
     */
    public static void close(InputStream in, OutputStream out) {
        SimpleFileRwUtil.close(in);
        SimpleFileRwUtil.close(out);
    }

    /**
     * 關閉輸入流
     * 
     * @param in
     */
    public static void close(InputStream in) {
        if (null != in) {
            try {
                in.close();
            } catch (IOException e) {
                // e.printStackTrace();
            }
        }
    }

    /**
     * 關閉輸出流
     * 
     * @param out
     */
    public static void close(OutputStream out) {
        if (null != out) {
            try {
                out.close();
            } catch (IOException e) {
                // e.printStackTrace();
            }
        }
    }

}
相關文章
相關標籤/搜索