借助JCharDet获取文件字符集

前段时间,在学习lucene的时候,遇到了读取txt文档遇到编码错误的问题。学了几个解决方案,大部分是将文件转十六进制(可以使用UE的Ctrl+H来查看),读取开头的四个标志位来判断。可是总有些文本文件无法识别(我遇到的是部分使用UTF-8编码的文件),后来发现了JCharDet。JCharDet是mozilla(就是firefox那家)的编码识别算法的Java实现,算了,这里是官网,自己看吧。

上代码:

package com.zhyea.util;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import org.mozilla.intl.chardet.nsDetector;
import org.mozilla.intl.chardet.nsICharsetDetectionObserver;

/**
 * 借助JCharDet获取文件字符集
 *
 * @author robin
 *
 */
public class FileCharsetDetector {

    /**
     * 字符集名称
     */
    private static String encoding;

    /**
     * 字符集是否已检测到
     */
    private static boolean found;

    private static nsDetector detector;

    private static nsICharsetDetectionObserver observer;

    /**
     * 适应语言枚举
     * @author robin
     *
     */
    enum Language{
        Japanese(1),
        Chinese(2),
        SimplifiedChinese(3),
        TraditionalChinese(4),
        Korean(5),
        DontKnow(6);

        private int hint;

        Language(int hint){
            this.hint = hint;
        }

        public int getHint(){
            return this.hint;
        }
    }

    /**
     * 传入一个文件(File)对象,检查文件编码
     *
     * @param file
     *            File对象实例
     * @return 文件编码,若无,则返回null
     * @throws FileNotFoundException
     * @throws IOException
     */
    public static String checkEncoding(File file) throws FileNotFoundException,
            IOException {
        return checkEncoding(file, getNsdetector());
    }

    /**
     * 获取文件的编码
     *
     * @param file
     *            File对象实例
     * @param language
     *            语言
     * @return 文件编码
     * @throws FileNotFoundException
     * @throws IOException
     */
    public static String checkEncoding(File file, Language lang)
            throws FileNotFoundException, IOException {
        return checkEncoding(file, new nsDetector(lang.getHint()));
    }

    /**
     * 获取文件的编码
     *
     * @param path
     *            文件路径
     * @return 文件编码,eg:UTF-8,GBK,GB2312形式,若无,则返回null
     * @throws FileNotFoundException
     * @throws IOException
     */
    public static String checkEncoding(String path) throws FileNotFoundException,
            IOException {
        return checkEncoding(new File(path));
    }

    /**
     * 获取文件的编码
     *
     * @param path
     *            文件路径
     * @param language
     *                 语言
     * @return
     * @throws FileNotFoundException
     * @throws IOException
     */
    public static String checkEncoding(String path, Language lang)
            throws FileNotFoundException, IOException {
        return checkEncoding(new File(path), lang);
    }

    /**
     * 获取文件的编码
     *
     * @param file
     * @param det
     * @return
     * @throws FileNotFoundException
     * @throws IOException
     */
    private static String checkEncoding(File file, nsDetector detector)
            throws FileNotFoundException, IOException {

        detector.Init(getCharsetDetectionObserver());

        if (isAscii(file, detector)) {
            encoding = "ASCII";
            found = true;
        }

        if (!found) {
            String prob[] = detector.getProbableCharsets();
            if (prob.length > 0) {
                encoding = prob[0];
            } else {
                return null;
            }
        }

        return encoding;
    }

    /**
     * 检查文件编码类型是否是ASCII型
     * @param file
     *             要检查编码的文件
     * @param detector
     * @return
     * @throws IOException
     */
    private static boolean isAscii(File file, nsDetector detector) throws IOException{
        BufferedInputStream input = null;
        try{
            input = new BufferedInputStream(new FileInputStream(file));

            byte[] buffer = new byte[1024];
            int hasRead;
            boolean done = false;
            boolean isAscii = true;

            while ((hasRead=input.read(buffer)) != -1) {
                if (isAscii)
                    isAscii = detector.isAscii(buffer, hasRead);
                if (!isAscii && !done)
                    done = detector.DoIt(buffer, hasRead, false);
            }

            return isAscii;
        }finally{
            detector.DataEnd();
            if(null!=input)input.close();
        }
    }

    /**
     * nsDetector单例创建
     * @return
     */
    private static nsDetector getNsdetector(){
        if(null == detector){
            detector = new nsDetector();
        }
        return detector;
    }

    /**
     * nsICharsetDetectionObserver 单例创建
     * @return
     */
    private static nsICharsetDetectionObserver getCharsetDetectionObserver(){
        if(null==observer){
            observer = new nsICharsetDetectionObserver() {
                public void Notify(String charset) {
                    found = true;
                    encoding = charset;
                }
            };
        }
        return observer;
    }
}

这个还存一个问题,就是识别Unicode编码的文件,会返回windows-1252。我使用windows-1252作为编码的时候会报错。

对了,再提供一个这个jar包下载的地址,官网有时会抽风,不能访问。

下载地址:http://download.csdn.net/detail/tianxiexingyun/8286849

就这样。

时间: 2024-08-03 07:19:40

借助JCharDet获取文件字符集的相关文章

获取文件字符集后转换成指定编码

package com.jiaotd.file; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.i

Java如何获取文件编码格式

1:简单判断是UTF-8或不是UTF-8,因为一般除了UTF-8之外就是GBK,所以就设置默认为GBK. 按照给定的字符集存储文件时,在文件的最开头的三个字节中就有可能存储着编码信息,所以,基本的原理就是只要读出文件前三个字节,判定这些字节的值,就可以得知其编码的格式.其实,如果项目运行的平台就是中文操作系统,如果这些文本文件在项目内产生,即开发人员可以控制文本的编码格式,只要判定两种常见的编码就可以了:GBK和UTF-8.由于中文Windows默认的编码是GBK,所以一般只要判定UTF-8编码

如何使用Java代码获取文件、文件流或字符串的编码方式

今天通过网络资源研究了一下如何使用Java代码获取文件.文件流或字符串的编码方式,现将代码与大家分享: package com.ghj.packageoftool; import info.monitorenter.cpdetector.io.ASCIIDetector; import info.monitorenter.cpdetector.io.ByteOrderMarkDetector; import info.monitorenter.cpdetector.io.CodepageDete

Atitit.检测文本文件的编码 自动获取文件的中文编码

Atitit.检测文本文件的编码 自动获取文件的中文编码 1 不能使用load来检测编码..1 2 使用convert来检测编码1 3 程序检测文本编码2 3.1 根据utf bom头2 3.2 检测字符 cpdetector2 4 ##实现原理 中文也走十gbk  utf8 unicode三中..只要试达的读取出来,在和汉字map相比..就能基于统计学原理...计算出来..2 1 不能使用load来检测编码.. 要是txt是 gbk的, 使用notepad++ load as utf8 三正常

WPF借助SaveFileDialog实现文件存储

以下是我的代码,对初涉WPF者有点用.wholestring是要写入文件的字符串. Microsoft.Win32.SaveFileDialog saveFileDialog = new Microsoft.Win32.SaveFileDialog(); //可能要获取的路径名 string localFilePath = "", fileNameExt = "", newFileName = "", FilePath = ""

C# 获取文件图标

今天突然想到一个问题,如何去获取一个文件的关联图标呢?于是就上网搜索了一下.现总结如下: 首先明确问题:获取一个文件的关联图标或者是某个类型文件的显示图标. 在网上搜了一圈,发现方法还是比较多的,但是应用C#进行获取的方法不多.我选择一种用.Net库的方法. 使用的类: System.Drawing.Icon ,位于System.Drawing 命名空间. 具体方法: System.Drawing.Icon 类中的静态方法:public static Icon ExtractAssociated

PHP中获取文件扩展名的N种方法

PHP中获取文件扩展名的N种方法 从网上收罗的,基本上就以下这几种方式: 第1种方法: function get_extension($file) { substr(strrchr($file, '.'), 1); } 第2种方法: function get_extension($file) { return substr($file, strrpos($file, '.')+1); } 第3种方法: function get_extension($file) { return end(expl

第九篇:使用 lstat 函数获取文件信息

前言 在之前的文章中,描述过如何用 fcntl 函数改变文件的状态标记.但,文件还有很多信息,如文件类型,权限设置,设备编号,访问时间等等.如果要获取这些信息,则使用函数 lstat 可以轻松达到这个目的. 下面的程序将使用该函数获取文件类型信息并判断它的类型. 但在这之前,先要说明文件信息结构体和文件类型判定宏. 文件信息结构体 调用 lstat 函数将会把指定文件的信息存放到 stat 结构体中,这个结构体的定义大致如下: 文件类型判定宏 文件结构体中的文件类型字段是一个整数,对此,可以使用

[Android Pro] 关于inputStream.available()方法获取文件的总大小

reference to :http://hold-on.iteye.com/blog/1017449 如果用inputStream对象的available()方法获取流中可读取的数据大小,通常我们调用这个函数是在下载文件或者对文件进行其他处理时获取文件的总大小. 以前在我们初学File和inputStream和outputStream时,有需要将文件从一个文件夹复制到另一个文件夹中,这时候我们用的就是inputStream.available()来获取文件的总大小,而且屡试不爽. 但是当我们要