JAVA实现自定义乱码判断逻辑
前言
在大数据日志收集中,出现各式各样的数据都不奇怪,因为前端采集的系统不能考虑到所有的突发情况。所以遇到乱码也是很常见的。那么出现乱码我们一般采取两种方式,要么保留,先存储到磁盘上,但是这种处理方式后续可能在分析落地数据库的时候会影响显示或者插入报错。第二种是直接过滤掉,放置后续的各种问题排查。不过我们还有第三种选择的,那就是自定义过滤乱码的数据。
⚠️⚠️⚠️引用文献
作者 | 地址 | 来源 |
---|---|---|
东边的小山 | https://blog.csdn.net/yelin042/article/details/82151636 | CSDN |
易霂 | https://www.jianshu.com/p/5590b8ef0dec | 简书 |
一、乱码是什么?
我们一般定义乱码就是非中文,非字母,非标点符合等之外的特殊字符。这是从一般理解上来定义的,那么从官方定义来讲。我这里说通俗点。也也就是在传输的过程中,字符的编码方式和解码方式不一致,就会造成乱码。举个🌰,MySQL的utf-8和utfmb4,前者使用一个字符三字节,后者使用一个字符4字节,这样的话,从前者数据库导数据到后者那么就会出现乱码。这就相当于你在我们国家学的法律制度,去了外国你要是还按照这个法律来就乱套了,人家不认。
二、自定义:视什么为乱码
⚡️⚡️⚡️⚡️代码注释很详细了,这里不多加解释了
package com.langjian;
import java.util.Base64;
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 GB18030与汉字兼容的垂直标点符号
|| ub == Character.UnicodeBlock.VERTICAL_FORMS
// ascii
|| ub == Character.UnicodeBlock.BASIC_LATIN
) {
return true;
} else {
return false;
}
}
/**
* 为了得到更为完整的可接受的字符表,定义isUserDefined方法(具体字符表与日志中的字符有关系);加上了Number Forms、Enclosed Alphanumerics、Letterlike Symbols这三个block,以及\u00a0(Non-breaking space)字符与\ufeff(ZERO WIDTH NO-BREAK SPACE)字符
*
* 简单来讲,就是我们在这可以提前录入一些我们提前已经知道不是乱码的符号
* 比如:Ⅱ 或者 ™
* @param c
* @return
*/
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;
}
public static void main(String[] args){
System.out.println(isMessy("天天四川麻将ⅡⅡⅡⅡⅡ™™™™™™™™™™™™™"));
//返回true
}
}
总结
以上就是关于自定义乱码的过滤逻辑,在我工作环境中,因为数据存储在集群上,使用读时模式不会太在意数据的格式类型包括是否乱码,展示的时候也不影响,有时候会过滤掉这部分乱码数据。不过如果是写入规范的数据库比如mysql,一般会采取处理和写入两方都保证一直的字符集来避免报错。