我有包含各种字符的字符串,需要写入谷歌BigQuery,这需要严格的UTF8字符串。当我尝试用各种各样的表情符号输入来编写字符串时,我得到一个错误:
java.lang.IllegalArgumentException: Unpaired surrogate at index 3373
at org.apache.beam.sdk.repackaged.com.google.common.base.Utf8.encodedLengthGeneral(Utf8.java:93)
at org.apache.beam.sdk.repackaged.com.google.common.base.Utf8.encodedLength(Utf8.java:67)
at org.apache.beam.sdk.coders.StringUtf8Coder.getEncodedElementByteSize(StringUtf8Coder.java:145)
...
我有一个解决这个问题的方法,可以简单地从字符串中剥离所有的代理字符:
private static String removeSurrogates(String query) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < query.length(); i++) {
char c = query.charAt(i);
if (!(Character.isHighSurrogate(c) || Character.isLowSurrogate(c))) {
sb.append(c);
}
}
return sb.toString();
}
但是,这会产生一个字符串,如
⚔⌨⛳⛏
减少到只有四个表情
⚔⌨⛳⛏
有没有一种适当的方法可以将这些字符转换为UTF8而不丢失,并且不使用未配对的代理?
(抱歉,我对字符集的总体理解不是很好)
发布于 2019-04-17 10:04:50
我找到问题了。我们使用org.apache.commons.lang3.StringEscapeUtils.unescapeHtml4将字符串中的HTML实体转换为它们的非编码形式。这似乎破坏了一些非拉丁字符。例如,通过此方法传递字符串"Italien“会将其转换为"Italien ?”(最后一个字符被破坏)
通过此方法传递"⚔⌨⛳⛏“将其转换为”?⚔⌨?⛳?“
import org.apache.commons.lang3.StringEscapeUtils;
public class CharacterTest {
public static void main(String[] args) {
String good = "⚔⌨⛳⛏";
String bad = StringEscapeUtils.unescapeHtml4(good);
System.out.println(good + "->" + bad);
}
}
⚔⌨⛳⛏->????????⚔⌨?⛳???
现在来找一个替代的HTML实体解码器...
发布于 2019-04-16 09:05:11
很有可能,如果你只是发送字符串,它会被转换成Is there a proper way to convert these characters into UTF8
-8。这就是Java编码器的工作方式。
如果没有,并且你正在发送二进制文件,你可以直接转换:
private static byte[] removeSurrogates(String query) {
return query.getBytes( "UTF-8" );
}
发布于 2019-04-16 11:08:43
让我暂时离开Java语言来展示一下BigQuery可以处理表情符号:
CREATE TABLE `public_dump.emoji_test`
AS
SELECT "⚔⌨⛳⛏" emojis
然后测试是否存在:
SELECT COUNT(*)
FROM `fh-bigquery.public_dump.emoji_test`
WHERE emojis LIKE '%%'
1
使用Python实现这一点很简单:
插入新数据也不是问题:
很抱歉,我不知道如何用Java解决这个问题,但我希望这能证明BigQuery的API能够优雅地处理表情符号。
https://stackoverflow.com/questions/55699140
复制相似问题