Q
工作中遇到ODPS数据同步至RDS的场景,数据中有emoji表情,同步任务(DataX)会把emoji表情标记为脏数据,然后跳过这条数据。如何将完整的数据同步完成?
A
1.更改rds数据库的字符集为utf8mb4:
我们的rds就是utf8mb4,但还是同步不过去。
2.更改同步脚本的encoding:
查看文档发现polarDB writer是通过jdbc链接rds for mysql 的,于是尝试更改jdbc的编码格式,但没有效果。也可能是语法格式问题,之前并不了解dataX脚本的语法。
3.过滤掉数据中的emoji:
改编码无果,时间紧迫,故开始尝试过滤掉emoji。起初是写sql,企图用正则表达式过滤,一步到位,但找了半天也没有能用的正则表达式。最后改用java语言写,创建UDF,终于过滤成功。
代码如下:
import com.aliyun.odps.udf.UDF;
import org.apache.commons.lang3.StringUtils;
public class EmojiFilter extends UDF {
public boolean isEmojiCharacter(char codePoint) {
return (codePoint == 0x0) || (codePoint == 0x9) || (codePoint == 0xA)
|| (codePoint == 0xD)
|| ((codePoint >= 0x20) && (codePoint <= 0xD7FF))
|| ((codePoint >= 0xE000) && (codePoint <= 0xFFFD))
|| ((codePoint >= 0x10000) && (codePoint <= 0x10FFFF));
}
public String evaluate(String s) {
String source = StringUtils.replace(s, s, " " + s);
if (StringUtils.isBlank(source)) {
return source;
}
StringBuilder buf = null;
int len = source.length();
for (int i = 0; i < len; i++) {
char codePoint = source.charAt(i);
if (isEmojiCharacter(codePoint)) {
if (buf == null) {
buf = new StringBuilder(source.length());
}
buf.append(codePoint);
}
}
if (buf == null) {
return source.trim();
} else {
if (buf.length() == len) {
buf = null;
return source.trim();
} else {
return buf.toString().trim();
}
}
}
}
代码源自这里:戳
Maxcompute创建UDF的方法:
- 下载 Maxcompute studio 插件
- 创建 MC项目
- 与maxcompute建立连接(Access ID和Key)
- 写代码(extends UDF)
- 打成带依赖的jar包
- 上传资源
- 创建UDF