文档章节

基于Cpdetector 检测文件编码

-悟空-
 -悟空-
发布于 2015/01/18 10:26
字数 917
阅读 1.8W
收藏 50

行业解决方案、产品招募中!想赚钱就来传!>>>

使用Cpdetector jar包,提供两种方式检测文件编码,至于选择哪种 需要根据个人需求,文档有注释。依赖antlr-2.7.4.jar,chardet-1.0.jar,jargs-1.0.jar三个jar包。 可以再官网下载 http://cpdetector.sourceforge.net/。

话不多说 附上代码:

package com.utils.encoding;

import info.monitorenter.cpdetector.io.ASCIIDetector;
import info.monitorenter.cpdetector.io.ByteOrderMarkDetector;
import info.monitorenter.cpdetector.io.CodepageDetectorProxy;
import info.monitorenter.cpdetector.io.JChardetFacade;
import info.monitorenter.cpdetector.io.ParsingDetector;
import info.monitorenter.cpdetector.io.UnicodeDetector;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;

import org.apache.log4j.Logger;

/**
 * <p>
 * 	获取流编码,不保证完全正确,设置检测策略 isFast为true为快速检测策略,false为正常检测
 * 	InputStream 支持mark,则会在检测后调用reset,外部可重新使用。
 * 	InputStream 流没有关闭。
 * </p>
 * 
 * <p>
 * 	如果采用快速检测编码方式,最多会扫描8个字节,依次采用的{@link UnicodeDetector},{@link byteOrderMarkDetector},
 * 	{@link JChardetFacade}, {@link ASCIIDetector}检测。对于一些标准的unicode编码,适合这个方式或者对耗时敏感的。
 * </p>
 * 
 * <p>
 * 	采用正常检测,读取指定字节数,如果没有指定,默认读取全部字节检测,依次采用的{@link byteOrderMarkDetector},{@link parsingDetector},{@link JChardetFacade}, {@link ASCIIDetector}检测。
 * 	字节越多检测时间越长,正确率较高。
 * </p>
 * @author WuKong
 *
 */
public class CpdetectorEncoding {
	
	private static final Logger logger = Logger.getLogger(CpdetectorEncoding.class);
	
	/**
	 * <p>
	 * 获取流编码,不保证完全正确,设置检测策略 isFast为true为快速检测策略,false为正常检测
	 * InputStream 支持mark,则会在检测后调用reset,外部可重新使用。
	 * InputStream 流没有关闭。
	 * </p>
	 * 
	 * <p>
	 * 如果采用快速检测编码方式,最多会扫描8个字节,依次采用的{@link UnicodeDetector},{@link byteOrderMarkDetector},
	 * {@link JChardetFacade}, {@link ASCIIDetector}检测。对于一些标准的unicode编码,适合这个方式或者对耗时敏感的。
	 * </p>
	 * 
	 * <p>
	 *  采用正常检测,读取指定字节数,如果没有指定,默认读取全部字节检测,依次采用的{@link byteOrderMarkDetector},{@link parsingDetector},{@link JChardetFacade}, {@link ASCIIDetector}检测。
	 *  字节越多检测时间越长,正确率较高。
	 * </p>
	 *
	 * @param in 输入流  isFast 是否采用快速检测编码方式
	 * @return Charset The character are now - hopefully - correct。如果为null,没有检测出来。
	 * @throws IOException 
	 */
	public Charset getEncoding(InputStream buffIn,boolean isFast) throws IOException{
		
		return getEncoding(buffIn,buffIn.available(),isFast);
	}
	
	public Charset getFastEncoding(InputStream buffIn) throws IOException{
		return getEncoding(buffIn,MAX_READBYTE_FAST,DEFALUT_DETECT_STRATEGY);
	}
	
	
	
	public Charset getEncoding(InputStream in, int size, boolean isFast) throws IOException {
		
		try {
			
			java.nio.charset.Charset charset = null;
			
			int tmpSize = in.available();
			size = size >tmpSize?tmpSize:size;
			//if in support mark method, 
			if(in.markSupported()){
				
				if(isFast){
					
					size = size>MAX_READBYTE_FAST?MAX_READBYTE_FAST:size;
					in.mark(size++);
					charset = getFastDetector().detectCodepage(in, size);
				}else{
					
					in.mark(size++);
					charset = getDetector().detectCodepage(in, size);
				}
				in.reset();
				
			}else{
				
				if(isFast){
					
					size = size>MAX_READBYTE_FAST?MAX_READBYTE_FAST:size;
					charset = getFastDetector().detectCodepage(in, size);
				}else{
					charset = getDetector().detectCodepage(in, size);
				}
			}
			
			
		    return charset;
		}catch(IllegalArgumentException e){
			
			logger.error(e.getMessage(),e);
			throw e;
		} catch (IOException e) {
			
			logger.error(e.getMessage(),e);
			throw e;
		}
		
	}
	
	
	public Charset getEncoding(byte[] byteArr,boolean isFast) throws IOException{
		
		return getEncoding(byteArr, byteArr.length, isFast);
	}
	
	
	public Charset getFastEncoding(byte[] byteArr) throws IOException{
		
		return getEncoding(byteArr, MAX_READBYTE_FAST, DEFALUT_DETECT_STRATEGY);
	}
	
	
	public Charset getEncoding(byte[] byteArr, int size,boolean isFast) throws IOException {
		
		size = byteArr.length>size?size:byteArr.length;
		if(isFast){
			size = size>MAX_READBYTE_FAST?MAX_READBYTE_FAST:size;
		}
		
		ByteArrayInputStream byteArrIn = new ByteArrayInputStream(byteArr,0,size);
		BufferedInputStream in = new BufferedInputStream(byteArrIn);
		
		try {
			
			Charset charset = null;
			if(isFast){
				
				charset = getFastDetector().detectCodepage(in, size);
			}else{
				
				charset = getDetector().detectCodepage(in, size);
			}
			
			return charset;
		} catch (IllegalArgumentException e) {
			
			logger.error(e.getMessage(),e);
			throw e;
		} catch (IOException e) {
			
			logger.error(e.getMessage(),e);
			throw e;
		}
	   
	}
	
	
	
	private static CodepageDetectorProxy detector =null;
	private static CodepageDetectorProxy fastDtector =null;
	private static ParsingDetector parsingDetector =  new ParsingDetector(false);
	private static ByteOrderMarkDetector byteOrderMarkDetector = new ByteOrderMarkDetector();
	
	//default strategy use fastDtector
	private static final boolean DEFALUT_DETECT_STRATEGY = true;
	
	private static final int MAX_READBYTE_FAST = 8; 
	
	private static CodepageDetectorProxy getDetector(){
		
		if(detector==null){
			
			detector = CodepageDetectorProxy.getInstance();
			 // Add the implementations of info.monitorenter.cpdetector.io.ICodepageDetector: 
		    // This one is quick if we deal with unicode codepages:
			detector.add(byteOrderMarkDetector);
			// The first instance delegated to tries to detect the meta charset attribut in html pages.
		    detector.add(parsingDetector);
		    // This one does the tricks of exclusion and frequency detection, if first implementation is 
		    // unsuccessful:
			detector.add(JChardetFacade.getInstance());
		    detector.add(ASCIIDetector.getInstance());
		}
		
		return detector;
	}
	
	
	private static CodepageDetectorProxy getFastDetector(){
		
		if(fastDtector==null){
			
			fastDtector = CodepageDetectorProxy.getInstance();
			fastDtector.add(UnicodeDetector.getInstance());
			fastDtector.add(byteOrderMarkDetector); 
			fastDtector.add(JChardetFacade.getInstance());
			fastDtector.add(ASCIIDetector.getInstance());
		}
		
		return fastDtector;
	}
	
}


-悟空-

-悟空-

粉丝 144
博文 25
码字总数 35562
作品 0
海淀
高级程序员
私信 提问
加载中
此博客有 3 条评论,请先登录后再查看。
树莓派(Raspberry Pi):完美的家用服务器

自从树莓派发布后,所有在互联网上的网站为此激动人心的设备提供了很多有趣和具有挑战性的使用方法。虽然这些想法都很棒,但树莓派( RPi )最明显却又是最不吸引人的用处是:创建你的完美家用...

异次元
2013/11/09
5.4K
8
代码生成器--Codgen

Codgen是一个基于数据库元数据模型,使用freemarker模板引擎来构建输出的代码生成器。freemarker的数据模型结构通常来说都是一个Map树状结构模型,codgen也不例外,它的数据模型这棵树的根节...

黄天政
2013/01/29
1.4W
2
Web开发组件管理器--Bower

Bower 是一个针对Web开发的包管理器。该工具主要用来帮助用户轻松安装CSS、JavaScript、图像等相关包,并管理这些包之间的依赖。 功能有些类似于Component。不同之处是,Component是围绕Git...

匿名
2013/02/01
1.2W
2
数据库代码辅助工具--MaoCaiJun.Database

MaoCaiJun.DataBase 是一个用于 Microsoft Visual Studio 的数据库代码生成组件。它是基于 xml 文件的代码创建工具,支持sql2000,sql2005,sql2008,access, SQLite MaoCaiJun.Database 数据库...

mccj
2013/02/06
2.2K
1
漏洞检测工具--Peach Fuzzer

Peach是一种用Python编写的 Fuzzer。这种工具有助于发现并公开许多漏洞,并认为是黑客和安全团体中最流行的工具之一。为了利用Peach框架,必须创建Phthon脚本,脚本 中包含了在服务器上执行的...

匿名
2013/02/06
8.7K
1

没有更多内容

加载失败,请刷新页面

加载更多

好用到爆的 Java 技巧

本文不是一个吹嘘的文章,不会讲很多高深的架构,相反,会讲解很多基础的问题和写法问题,如果读者自认为基础问题和写法问题都是不是问题,那请忽略这篇文章,节省出时间去做一些有意义的事情...

码农突围
39分钟前
8
0
消息队列(MessageQueue)-分析

这里分析消息队列的原理和一般做法和其理念价值 这里还会 分析 NATS 和其可改进点 TODO

梦想游戏人
43分钟前
20
0
Redis 教程

Redis 教程 REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统。 Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的...

rootliu
46分钟前
9
0
SPSSAU 付费数据研究报告服务

SPSSAU-付费数据分析报告服务(周老师提供) 本文分享自微信公众号 - SPSSAU(spssau)。 如有侵权,请联系 support@oschina.cn 删除。 本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起...

SPSSAU
2017/11/08
0
0
芋艿-springcloud gateway

http://www.iocoder.cn/Spring-Cloud/Spring-Cloud-Gateway/?github springcloud gateway 官方文档 https://cloud.spring.io/spring-cloud-gateway/reference/html/#gatewayfilter-factories......

Java搬砖工程师
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部