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