简单文件读写的工具类(使用字节流工具类实现)

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

}

猜你喜欢

转载自www.cnblogs.com/zj0208/p/9104031.html