最近在日志数据清洗时遇到中文乱码,如果只要有非中文字符就将该字符串过滤掉,这种方法虽简单但并不可取,因为比如像Xperia™主題天天四川麻将Ⅱ这样的字符串也会被过滤掉。

1. Unicode编码

Unicode编码是一种涵盖了世界上所有语言、标点等字符的编码方式,简单一点说,就是一种通用的世界码;其编码范围:U+0000 .. U+10FFFF。按Unicode硬编码的区间进行划分,Unicode编码被分成若干个block ( Unicode block);每一个Unicode编码专属于唯一的Unicode block,Unicode block之间互不重叠。从码字的本身的属性出发,Unicode编码被分成了若干script ( Unicode script);比如,与中文相关的字符、标点的scriptHan包括block如下:

  • CJK Radicals Supplement
  • Kangxi Radicals
  • CJK Symbols and Punctuation中的15个字符
  • CJK Unified Ideographs Extension A
  • CJK Unified Ideographs
  • CJK Compatibility Ideographs
  • CJK Unified Ideographs Extension B
  • CJK Unified Ideographs Extension C
  • CJK Unified Ideographs Extension D
  • CJK Unified Ideographs Extension E
  • CJK Compatibility Ideographs Supplement

其中,常见的中文字符在CJK Unified Ideographs block;此外,考虑繁体字及不常见字等,CJK还有A、B、C、D、E五个extension。Basic Latin block完整地包含了ASCII码的控制字符、标点字符与英文字母字符。

Unicode编码与block、script之间的映射关系,具体可参看这里

2. Java的字符编码

JDK完整实现Unicode的block与script:

Char c = '☎'
Character.UnicodeBlock ub = Character.UnicodeBlock.of(c)
Character.UnicodeScript uc = Character.UnicodeScript.of(c);

Java中的字符char内置的编码方式是UTF-16,当char强转成int类型时,其返回值是unicode编码值,只有当getbyte时才返回的是utf-8编码的byte:

String s = "\u00a0";
String.format("\\u%04x", (int) s.charAt(0)) // --> \u00a0
import org.apache.commons.codec.binary.Hex;
Hex.encodeHex(s.getBytes()) // --> c2a0

UTF-8是Unicode字符的变长前缀编码的一种实现,二者之间的对应关系在这里.现在我们回到开篇过滤中文乱码的问题,有一个基本解决思路:

  • 去掉各种标点字符、控制字符,
  • 计算剩下字符中非中文字符所占的比例,如果超过阈值,则认为该字符串为乱码串

完整代码如下:

public class ChineseUtill {

    private static boolean isChinese(char c) {
Character.UnicodeScript sc = Character.UnicodeScript.of(c);
if (sc == Character.UnicodeScript.HAN) {
return true;
}
return false;
} public static boolean isPunctuation(char c) {
Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
if ( // punctuation, spacing, and formatting characters
ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
// symbols and punctuation in the unified Chinese, Japanese and Korean script
|| ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
// fullwidth character or a halfwidth character
|| ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS
// vertical glyph variants for east Asian compatibility
|| ub == Character.UnicodeBlock.CJK_COMPATIBILITY_FORMS
// vertical punctuation for compatibility characters with the Chinese Standard GB 18030
|| ub == Character.UnicodeBlock.VERTICAL_FORMS
// ascii
|| ub == Character.UnicodeBlock.BASIC_LATIN
) {
return true;
} else {
return false;
}
} private static Boolean isUserDefined(char c) {
Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
if (ub == Character.UnicodeBlock.NUMBER_FORMS
|| ub == Character.UnicodeBlock.ENCLOSED_ALPHANUMERICS
|| ub == Character.UnicodeBlock.LETTERLIKE_SYMBOLS
|| c == '\ufeff'
|| c == '\u00a0'
)
return true;
return false;
} public static Boolean isMessy(String str) {
float chlength = 0;
float count = 0;
for(int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if(isPunctuation(c) || isUserDefined(c))
continue;
else {
if(!isChinese(c)) {
count = count + 1;
}
chlength ++;
}
}
float result = count / chlength;
if(result > 0.3)
return true;
return false;
} }

为了得到更为完整的可接受的字符表,定义isUserDefined方法(具体字符表与日志中的字符有关系);加上了Number FormsEnclosed AlphanumericsLetterlike Symbols这三个block,以及\u00a0(Non-breaking space)字符与\ufeff(ZERO WIDTH NO-BREAK SPACE)字符。

3. 参考资料

[1] Wikipedia, Unicode block.

[2] Tong Zeng, Java 中文字符判断 中文标点符号判断.

Java实现过滤中文乱码的更多相关文章

  1. java socket输入输出中文乱码问题

    http://hi.baidu.com/linjk03/item/e2028bfd990c14ea1a111feb 统一了输入输出的编码格式,是不会有乱码问题出现的.   构造Reader或Write ...

  2. java: jsp:param中文乱码

    java: jsp:param中文乱码 假如a.jsp/b.jsp文件中 a.jsp代码: 需要加入:request.setCharacterEncoding("UTF-8")  ...

  3. Java编程中中文乱码问题的研究及解决方案

    0 引言 Java最大的特性是与平台的无关性及开发环境的多样性.字符串被Java应用程序转化之前,是根据操作系统默认的编码方式编码.Java语言内部采用Unicode编码,它是定长双字节编码,即任何符 ...

  4. java开发中中文乱码总结

    1.jsp页面内容显示乱码 这种乱码原因很简单,一般的工具或解码程序对中文字符解析时采用默认的解码方式: <%@ page contentType="text/html; charse ...

  5. java链接mysql 中文乱码

    {转!} 背景: 由于最近在开发一个APP的后台程序,需要Java连接远程的MySQL数据库进行数据的更新和查询操作,并且插入的数据里有中文,在插入到数据库后发现中文都是乱码.网上查了很多教程,最后都 ...

  6. 201671010127 2016—2017—2 Java怎样解决Java程序中中文乱码的问题。

    这是本次第二次分享新手在编程中遇到的问题,相信很多Java新手和我一样,在Java编程中会遇到中文乱码的情况,下面我就给大家分享我遇到问题和解决问题的具体过程. 我先用Notepad++写了一个如下的 ...

  7. 解决Ubuntu下的Eclipse打开Windows编写的java代码的中文乱码

    其实所有的中文乱码 问题都是编码不同所导致的.这里要想让eclipse能正常显示出汉字,就要修改它的字符编码 步骤如下: 1 ,点击菜单栏中的Window(窗口),选择Preferences(首选项) ...

  8. java 页面传输中文乱码解决方式

    post 中文乱码解决方案 接受数据的时候设置 request.setCharacterEncoding("utf-8");//编码必须和页面编码一致 页面设置 <%@pag ...

  9. JAVA下载文件中文乱码问题

    http://blog.itpub.net/92037/viewspace-788900/ 最后的中文乱码没有解决 现在我在系统中用到了两个组件,smartupload,一个支持中文,一个不支持.但是 ...

随机推荐

  1. oracle在impdp时报ORA-31655和ORA-39154

    检查表空间大小设置的是否合理. 另外可以试试 grant IMP_FULL_DATABASE to user;增加导入权限. (转)

  2. vs的dll引用机制

    vs2012编译的时候,遇到一个问题就是项目A中运行时缺失dll的问题,项目A引用类库B,类库B引用了x,y等dll,编译A项目的时候,出现x没拷贝到bin 目录. 通过跟踪编译输出发现,x没拷贝的原 ...

  3. mono的远程调试

    mono可以让.net程序运行在linux平台上.于是.net程序员有了mono之后就转身跨平台了.但开放环境往往还是在windows下,于是有了这样的需求,是否可以用windows下的源码来实机调试 ...

  4. UML动态模型图简单介绍

    UML动态模型图描述了系统动态行为的各个方面,包括用例图.序列图.协作图.活动图和状态图.下面就每种图做一个简单介绍: 用例图 用例图描述系统外部的执行者与系统提供的用例之间的某种联系.所谓用例是指对 ...

  5. jQuery+ASP.NET MVC基于CORS实现带cookie的跨域ajax请求

    这是今天遇到的一个实际问题,在这篇随笔中记录一下解决方法. ASP.NET Web API提供了CORS支持,但ASP.NET MVC默认不支持,需要自己动手实现.可以写一个用于实现CORS的Acti ...

  6. Web Essentials之Bundling

    返回Web Essentials功能目录 本篇目录 介绍 样例文件 已知行为 介绍 这篇要讲的是Bundling,我看很多人把它翻译为捆绑,如果你喜欢你也可以这么理解,我是不太习惯,我还是喜欢它为bu ...

  7. RCP: JDT 根据org.eclipse.jdt.core.IJavaElement对象获取org.eclipse.jdt.core.dom.ASTNode对象

    JDT中有两套Java文件模型映射. 其核心类\接口分别为: org.eclipse.jdt.core.IJavaElement和org.eclipse.jdt.core.dom.ASTNode IJ ...

  8. Alpha阶段冲刺总结

    Alpha阶段冲刺阶段总结 预期计划: 本阶段的预期计划是实现打地鼠游戏的基本功能,包括:游戏功能.难度调节功能.计时功能.计数记分功能.DIY设置功能.分数记录功能. 实际进展: 在经过三周的Alp ...

  9. IE浏览器不能自动显示PDF文件的解决办法

    今天更新了Adobe的PDF Reader,更新后发现在网页上无法预览PDF文件了,点击PDF的连接,浏览器就会提示下载或者打开,感觉很不爽,经过一番百度,找到了解决办法,在这里分享一下. 打开IE浏 ...

  10. [ZigBee] 15、Zigbee协议栈应用(一)——Zigbee协议栈介绍及简单例子(长文,OSAL及Zigbee入门知识)

    1.Zigbee协议栈简介 协议是一系列的通信标准,通信双方需要按照这一标准进行正常的数据发射和接收.协议栈是协议的具体实现形式,通俗讲协议栈就是协议和用户之间的一个接口,开发人员通过使用协议栈来使用 ...