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
结果还是没有转码。