Java以任意编码格式加载文本文件

1 篇文章 0 订阅
1 篇文章 0 订阅

Java以任意编码格式加载文本文件

找了很多java文本本文件编码获取的,都不靠谱,最后找到了一个博客java 获取文本文件编码格式可以正常使用,贴在这里以供备忘。

我看到的大多数获取文本文件的编码格式都仅仅是通过读取开头三个字节的数据来判断文本的编码格式,但是经过我的测试,当文本开头为ASCII字符等的时候,无法正确判断出文件所采用的编码格式,我对这个方法的理解为,先通过判断开头的三个字节,如果无法判断则以字节流的形式遍历文件,通过测试每个字节的方式判断编码格式。

/**
 * @file FileUtil.java
 * @package default
 * @author Wagsn
 * @date 2018年8月12日
 * @version 1.0.0
 */

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;

import org.junit.Test; // JUint 4 Library

/**
 * @class FileUtil
 * @author Wagsn
 * @date 2018年8月12日
 * @version 1.0.0
 */
public class FileUtil {

    /**
     * 示例文件路径
     */
    public static String path = "./files/expression_src.ws";

    /**
     * JUint 4 单元测试,测试加载方法是否正常
     * 
     * @throws Exception
     */
    @Test
    public void testLoad() {
        System.out.println("--文件-> [" + path + "] 的内容如下:\n" + load(path)); // 在控制台没有打印出换行
    }

    /**
     * 加载文件通过路径从文件系统。
     * TODO 将path扩展为URL,并增加路径检查
     * 
     * @param path
     * @return
     * @throws Exception
     */
    public static StringBuffer load(String path) {
        StringBuffer buffer = new StringBuffer("");
        try {
            String code = charset(path);
            BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(new File(path)), code));
            String temp = null;
            while ((temp = br.readLine()) != null) {
                buffer.append(temp);
            }
            br.close();
            return buffer;
        } catch (Exception e) {
            System.err.println("--读取文件-> [" + path + "] 失败!");
            e.printStackTrace();
        }
        return buffer; // buffer.length()==0
    }

    /**
     * 判断文本文件的字符集,文件开头三个字节表明编码格式。 
     * <a href="http://blog.163.com/wf_shunqiziran/blog/static/176307209201258102217810/">参考的博客地址</a>
     * 
     * @param path
     * @return
     * @throws Exception
     * @throws Exception
     */
    public static String charset(String path) {
        String charset = "GBK";
        byte[] first3Bytes = new byte[3];
        try {
            boolean checked = false;
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(path));
            bis.mark(0); // 读者注: bis.mark(0);修改为 bis.mark(100);我用过这段代码,需要修改上面标出的地方。 
                        // Wagsn注:不过暂时使用正常,遂不改之
            int read = bis.read(first3Bytes, 0, 3);
            if (read == -1) {
                bis.close();
                return charset; // 文件编码为 ANSI
            } else if (first3Bytes[0] == (byte) 0xFF && first3Bytes[1] == (byte) 0xFE) {
                charset = "UTF-16LE"; // 文件编码为 Unicode
                checked = true;
            } else if (first3Bytes[0] == (byte) 0xFE && first3Bytes[1] == (byte) 0xFF) {
                charset = "UTF-16BE"; // 文件编码为 Unicode big endian
                checked = true;
            } else if (first3Bytes[0] == (byte) 0xEF && first3Bytes[1] == (byte) 0xBB
                    && first3Bytes[2] == (byte) 0xBF) {
                charset = "UTF-8"; // 文件编码为 UTF-8
                checked = true;
            }
            bis.reset();
            if (!checked) {
                while ((read = bis.read()) != -1) {
                    if (read >= 0xF0)
                        break;
                    if (0x80 <= read && read <= 0xBF) // 单独出现BF以下的,也算是GBK
                        break;
                    if (0xC0 <= read && read <= 0xDF) {
                        read = bis.read();
                        if (0x80 <= read && read <= 0xBF) // 双字节 (0xC0 - 0xDF)
                            // (0x80 - 0xBF),也可能在GB编码内
                            continue;
                        else
                            break;
                    } else if (0xE0 <= read && read <= 0xEF) { // 也有可能出错,但是几率较小
                        read = bis.read();
                        if (0x80 <= read && read <= 0xBF) {
                            read = bis.read();
                            if (0x80 <= read && read <= 0xBF) {
                                charset = "UTF-8";
                                break;
                            } else
                                break;
                        } else
                            break;
                    }
                }
            }
            bis.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("--文件-> [" + path + "] 采用的字符集为: [" + charset + "]");
        return charset;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值