java - 如何在没有未配对代理字符的情况下将表情符号等字符编码为 UTF8?
问题描述
我有需要写入 Google 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 而不会丢失,并且不使用不成对的代理?
(抱歉,我对一般字符集的理解不是很好)
解决方案
我发现了问题。我们正在使用 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 实体解码器......
推荐阅读
- java - Logback Appender 的静态上下文配置
- java - 按“前缀优先”逻辑对弹性命中进行排序
- regex - 匹配具有特定文本并在方括号内以 _P 结尾的行
- javascript - 页面第一次重新加载时 reactjs 的平滑滚动条问题
- javascript - 香草javascript中的单选按钮检查不起作用
- c# - MessageBox 出现三次后如何关闭表单?
- java - 如何将 xml 转换为 json 或 javabean?
- javascript - 在 VueJS 中为表的映射数组制作自定义函数
- ruby-on-rails - 部署到 Heroku 时,rails 应用程序的导航栏消失
- amazon-web-services - AWS Cognito 和 OAuth 2.0 登录