java自动识别文本文件字符编码

编程开发中,免不了要读取磁盘中的文本文件,目前文本文件最常用的是使用“utf-8”及“gbk”字符编码,如果使用了错误的字符编码格式,就会发生乱码的问题,因而在读取前,需要约定好要读取的文本文件内容与工程代码字符编码的统一。如果程序能够自动在读取文件时,能够识别其字符编码,固然就happy了。

这是我目前写的小工具,目前测试能够很好的识别读取的文本文件是“utf-8”还是“gbk”,原理是这2种字符编码的英文字母及标点字符都是ASCII码,“utf-8”分有bom头与无bom头的情况,“utf-8”的中文字符的16进制编码基本是以“E”开头,那么,就根据这些特征进行猜测,代码如下:

 

package top.hmtools.base;

import java.math.BigInteger;

import top.hmtools.system.SystemInfoTools;

/**
 * 猜测字符编码工具
 * @author HyboJ
 *
 */
public class CharsetGuessTools {

	/**
	 * 根据字节码数组,猜测编码类型
	 * 
依据:如果文本头有bom信息则可知其对应的字符编码。 *
此外,GBK与UTF-8都有可能,二者都可以没有bom信息。经观察发现,ASCII对应的字符是二者一致的部分, *
经尝试多个中文字符,发现在UTF-8中的编码在以16进制字符串表示时,基本上是以“E”开头,而GBK则不是。 *
准确性还有待验证,如果猜测不准确,请联系作者:嗨啵 *
电子邮箱:[email protected] * @param bytes * @return */ public static String doGuess(byte[] bytes){ if(bytes ==null || bytes.length<1){ return null; } //如果含有bom头信息的话 String string = binary(bytes); ECharsetBom[] bomHeads = ECharsetBom.values(); for(ECharsetBom bom:bomHeads){ if(string.toUpperCase().startsWith(bom.getBomHead().toUpperCase())){ return bom.getEncodeName(); } } //没有bom头信息的话 for(byte bt:bytes){ String hex = byteToHex(bt); //忽略ASCII码部分 int btInt = Integer.parseInt(hex, 16); if(btInt<128&&btInt>=0){ continue; } if(hex.toUpperCase().startsWith("E")){ return "UTF-8"; }else{ return "GBK"; } } if(SystemInfoTools.isLinux()){ return "UTF-8"; }else if(SystemInfoTools.isWindows()){ return "GBK"; }else{ return "GB2312"; } } private static final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; /** * 将单个byte转换为16进制表示的字符串 * @param b * @return */ private static String byteToHex(byte b){ char[] buf = new char[2]; int a = 0; int index = 0; if(b < 0) { a = 256 + b; } else { a = b; } buf[index++] = HEX_CHAR[a / 16]; buf[index++] = HEX_CHAR[a % 16]; return new String(buf); } /** * 将字节码数组转换为指定的进制字符串 */ private static String binary(byte[] bytes) { // 一个byte为8位,可用两个十六进制位标识 char[] buf = new char[bytes.length * 2]; int a = 0; int index = 0; for(byte b : bytes) { // 使用除与取余进行转换 if(b < 0) { a = 256 + b; } else { a = b; } buf[index++] = HEX_CHAR[a / 16]; buf[index++] = HEX_CHAR[a % 16]; } return new String(buf); } }

 

 

 

源代码工程主页:https://gitee.com/hm-tools/hm-tools-common/blob/master/src/main/java/top/hmtools/base/CharsetGuessTools.java

如有识别异常的情况,可邮件至:j#hybo.net (“#”改为“@”,你懂的~~)

你可能感兴趣的:(java)