http://yongboy.iteye.com/blog/266501
依赖一个 Mozilla 开源的 JAR 包。基于统计来进行字符集探查的,所以并不是百分百准确,并且需要字符串样本足够长。
package org.mozilla.intl.chardet; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; /** * 借助JCharDet获取文件字符集 * @author icer * PS: * JCharDet 是mozilla自动字符集探测算法代码的java移植,其官方主页为: * http://jchardet.sourceforge.net/ * @date 2008/11/13 */ public class FileCharsetDetector { private boolean found = false; /** * 如果完全匹配某个字符集检测算法, 则该属性保存该字符集的名称. 否则(如二进制文件)其值就为默认值 null, 这时应当查询属性 */ private String encoding = null; public static void main(String[] argv) throws Exception { if (argv.length != 1 && argv.length != 2) { System.out .println("Usage: FileCharsetDetector <path> [<languageHint>]"); System.out.println(""); System.out.println("Where <path> is d:/demo.txt"); System.out.println("For optional <languageHint>. Use following..."); System.out.println(" 1 => Japanese"); System.out.println(" 2 => Chinese"); System.out.println(" 3 => Simplified Chinese"); System.out.println(" 4 => Traditional Chinese"); System.out.println(" 5 => Korean"); System.out.println(" 6 => Dont know (default)"); return; } else { String encoding = null; if (argv.length == 2) { encoding = new FileCharsetDetector().guestFileEncoding(argv[0], Integer.valueOf(argv[1])); } else { encoding = new FileCharsetDetector().guestFileEncoding(argv[0]); } System.out.println("文件编码:" + encoding); } } /** * 传入一个文件(File)对象,检查文件编码 * * @param file * File对象实例 * @return 文件编码,若无,则返回null * @throws FileNotFoundException * @throws IOException */ public String guestFileEncoding(File file) throws FileNotFoundException, IOException { return geestFileEncoding(file, new nsDetector()); } /** * 获取文件的编码 * * @param file * File对象实例 * @param languageHint * 语言提示区域代码 eg:1 : Japanese; 2 : Chinese; 3 : Simplified Chinese; * 4 : Traditional Chinese; 5 : Korean; 6 : Dont know (default) * @return 文件编码,eg:UTF-8,GBK,GB2312形式,若无,则返回null * @throws FileNotFoundException * @throws IOException */ public String guestFileEncoding(File file, int languageHint) throws FileNotFoundException, IOException { return geestFileEncoding(file, new nsDetector(languageHint)); } /** * 获取文件的编码 * * @param path * 文件路径 * @return 文件编码,eg:UTF-8,GBK,GB2312形式,若无,则返回null * @throws FileNotFoundException * @throws IOException */ public String guestFileEncoding(String path) throws FileNotFoundException, IOException { return guestFileEncoding(new File(path)); } /** * 获取文件的编码 * * @param path * 文件路径 * @param languageHint * 语言提示区域代码 eg:1 : Japanese; 2 : Chinese; 3 : Simplified Chinese; * 4 : Traditional Chinese; 5 : Korean; 6 : Dont know (default) * @return * @throws FileNotFoundException * @throws IOException */ public String guestFileEncoding(String path, int languageHint) throws FileNotFoundException, IOException { return guestFileEncoding(new File(path), languageHint); } /** * 获取文件的编码 * * @param file * @param det * @return * @throws FileNotFoundException * @throws IOException */ private String geestFileEncoding(File file, nsDetector det) throws FileNotFoundException, IOException { // Set an observer... // The Notify() will be called when a matching charset is found. det.Init(new nsICharsetDetectionObserver() { public void Notify(String charset) { found = true; encoding = charset; } }); BufferedInputStream imp = new BufferedInputStream(new FileInputStream( file)); byte[] buf = new byte[1024]; int len; boolean done = false; boolean isAscii = true; while ((len = imp.read(buf, 0, buf.length)) != -1) { // Check if the stream is only ascii. if (isAscii) isAscii = det.isAscii(buf, len); // DoIt if non-ascii and not done yet. if (!isAscii && !done) done = det.DoIt(buf, len, false); } det.DataEnd(); if (isAscii) { encoding = "ASCII"; found = true; } if (!found) { String prob[] = det.getProbableCharsets(); if (prob.length > 0) { // 在没有发现情况下,则取第一个可能的编码 encoding = prob[0]; } else { return null; } } return encoding; } }
另外参见:encodechecker v0.5 文件编码自动检测及编码转换 GitHub
目前支持如下编码格式
GBK
US-ASCII
ISO-8859-1
utf-8_withoutBom
utf-8_withBom
UTF-16BE_withBom
UTF-16BE_withoutBom
UTF-16LE_withBom
UTF-16LE_withoutBom
UTF-32BE_withBom
UTF-32BE_withoutBom
UTF-32LE_withBom
UTF-32LE_withoutBom
JAVA Unicode 编码和汉字的相互转换
import java.util.regex.Matcher; import java.util.regex.Pattern; /** * 时间:2009-8-25 * * 作者:【轰隆隆】 */ public class T10_BianMa { /** * java unicode 的相互转换 */ public T10_BianMa() { } public static void main(String[] args){ System.out.println(UnicodeToString("\速\度\中\国")); String chinese = "中华人民共和国"; for(int i = 0;i<chinese.length();i++){ System.out.print("\\u" + Integer.toHexString(chinese.charAt(i))); //System.out.print(chinese.getBytes("Unicode")[i]); } System.out.println(); String str = "\中\华\人\民\共\和\国"; for(int j = 0;j<str.length();j++) { System.out.println(str.charAt(j)); } } public static String UnicodeToString(String str) { Pattern pattern = Pattern.compile("(\\\\u(\\p{XDigit}{4}))"); Matcher matcher = pattern.matcher(str); char ch; while (matcher.find()) { ch = (char) Integer.parseInt(matcher.group(2), 16); str = str.replace(matcher.group(1), ch + ""); } return str; } }
将JDK的bin目录加入系统变量path。在盘下建立一个test目录,在test目录里建立一个zh.txt文件,
文件内容为:“熔岩”,打开“命令行提示符”,并进入C:\test目录下。下面就可以按照说明一步一步来操作,注意观察其中编码的变化。
A:将zh.txt转换为Unicode编码,输出文件到u.txt
native2ascii zh.txt u.txt
打开u.txt,内容为“\熔\岩”。
B:将zh.txt转换为Unicode编码,输出到控制台 --Unicode输出文件
C:\test>native2ascii zh.txt
\熔\岩
可以看到,控制台输出了“\熔\岩”。
C:将zh.txt转换为ISO8859-1编码,输出文件到i.txt
native2ascii -encoding ISO8859-1 zh.txt i.txt
打开i.txt文件,内容为“\?\?\?\?”。
D:将u.txt转换为本地编码,输出到文件u_nv.txt --输出文件
native2ascii -reverse u.txt u_nv.txt
打开u_nv.txt文件,内容为“熔岩”。
E:将u.txt转换为本地编码,输出到控制台
C:\test>native2ascii -reverse u.txt
熔岩
可以看到,控制台输出了“熔岩”。
F:将i.txt转换为本地编码,输出到i_nv.txt
native2ascii -reverse i.txt i_nv.txt
打开i_nv.txt文件,内容为“\?\?\?\?”。发现转码前后完全一样的。也就是说,等于没有转,或者说思想糊涂,对命名没有理解。。
G:将i.txt转换为GBK编码,输出到i_gbk.txt
native2ascii -reverse -encoding GBK i.txt i_gbk.txt
打开i_gbk.txt文件,内容为“\?\?\?\?”。发现转码前后完全一样的。也就是说,等于没有转,或者说思想糊涂,对命名没有理解。
H:将u_nv.txt转码到本地编码GBK,输出到控制台
C:\test>native2ascii -reverse -encoding ISO8859-1 i.txt
熔岩
从这个结果看,目标达到到了,编码i.txt为ISO8859-1,转为本地编码后内容为“熔岩”。
从这里应该意识到,native2ascii -reverse命令中-encoding指定的编码为源文件的编码格式。
而在native2ascii 命令中-encoding指定的编码为(生成的)目标文件的编码格式。这一点非常的重要!切记!!
继续探索,新建文件12a.txt,内容“12axyz”。看看纯字母数字的编码又如何。
I:将纯字母数字的文本文件12a.txt转换为Unicode编码
native2ascii 12a.txt 12a_nv.txt
打开12a_nv.txt文件,内容为“12axyz”。
继续测试,转为ISO8859-1编码看看
C:\test>native2ascii -encoding ISO8859-1 12a.txt
12axyz
结果还是没有转码。