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(); } } } }