在讀取文件時,如果不清楚文件編碼或者在不同的編碼環境拷貝文件,這時中文數據很可能會出現亂碼,參考了博客:http://blog.csdn.net/servermanage/article/details/8595676,有了如下的代碼:
/**
* 檢測文件的編碼和文本流的編碼
* 參考: http://blog.csdn.net/servermanage/article/details/8595676
* @author Administrator
*
*/
public class CpdetectorUtils {
//獲取文本編碼
private static final String FILE_ENCODE_TYPE = "file";
//獲取文件流編碼
private static final String IO_ENCODE_TYPE = "io";
/**
* 獲取探測到的文件對象
*
* @param path
* 要判斷文件編碼格式的源文件的路徑
*/
private CodepageDetectorProxy getDetector() {
/*
* detector是探測器,它把探測任務交給具體的探測實現類的實例完成。
* cpDetector內置了一些常用的探測實現類,這些探測實現類的實例可以通過add方法 加進來,如ParsingDetector、
* JChardetFacade、ASCIIDetector、UnicodeDetector。
* detector按照“誰最先返回非空的探測結果,就以該結果爲準”的原則返回探測到的
* 字符集編碼。使用需要用到三個第三方JAR包:antlr.jar、chardet.jar和cpdetector.jar
* cpDetector是基於統計學原理的,不保證完全正確。
*/
CodepageDetectorProxy detector = CodepageDetectorProxy.getInstance();
/*
* ParsingDetector可用於檢查HTML、XML等文件或字符流的編碼,構造方法中的參數用於
* 指示是否顯示探測過程的詳細信息,爲false不顯示。
*/
detector.add(new ParsingDetector(false));
/*
* JChardetFacade封裝了由Mozilla組織提供的JChardet,它可以完成大多數文件的編碼
* 測定。所以,一般有了這個探測器就可滿足大多數項目的要求,如果你還不放心,可以
* 再多加幾個探測器,比如下面的ASCIIDetector、UnicodeDetector等。
*/
detector.add(JChardetFacade.getInstance());// 用到antlr.jar、chardet.jar
// ASCIIDetector用於ASCII編碼測定
detector.add(ASCIIDetector.getInstance());
// UnicodeDetector用於Unicode家族編碼的測定
detector.add(UnicodeDetector.getInstance());
return detector;
}
/**
* 根據"encodeType"獲取文本編碼或文件流編碼
*/
public String getFileOrIOEncode(String path,String encodeType){
CodepageDetectorProxy detector = getDetector();
File file = new File(path);
Charset charset = null;
try {
switch (encodeType) {
case FILE_ENCODE_TYPE:
charset = detector.detectCodepage(file.toURI().toURL());
break;
case IO_ENCODE_TYPE:
charset = detector.detectCodepage(new BufferedInputStream(new FileInputStream(file)),128);//128表示讀取128字節來判斷文件流的編碼,讀得越多越精確,但是速度慢
break;
default:
charset = Charset.defaultCharset();
break;
}
} catch (IOException e) {
//這裏獲取編碼失敗,使用系統默認的編碼
charset = Charset.defaultCharset();
System.out.println(e.getMessage());
}
return charset.name();
}
@Test
public void test(){
String path = "F:/DevelopmentSoftware/2016-04-18至2016-04-24記錄.txt";
System.out.println("文件編碼: " + getFileOrIOEncode(path, FILE_ENCODE_TYPE));
System.out.println("文件流編碼: " + getFileOrIOEncode(path, IO_ENCODE_TYPE));
}
}
測試結果如下:
文件編碼: GB2312
文件流編碼: GB2312
尤其要注意在獲取文件流編碼時,重載方法detector.detectCodepage(new BufferedInputStream(new FileInputStream(file)),128);的第一個參數必須是包裝的高級流,如果是FileInputStream會包參數異常錯誤.