如何解决这种格式是:“U+043E;U+006F,U+004D”某种编码标准,java 是否提供了标准库方法将其转换为字符?
我正在调查对我们的语言支持所做的一些混乱(它用于我们的 IDN 功能,如果这会敲响警钟的话)...
我使用 SQL GUI 客户端来快速查看我们的语言定义的结构。因此,当我执行 select charcodes from ourCharCodesTable where language = 'myLanguage';
时,我会得到某些 'myLanguage'
值的结果,例如:
myLanguage = "ASCII"
:result = "-0123456789abcdefghijklmnopqrstuvwxyz"
myLanguage = "Russian"
:result = "-0123456789абвгдежзийклмнопрстуфхцчшщъьюяѐѝ"
(顺便说一句:如果你像我一样多语言的话,这里已经可以看到语言错误了!)
我想:“好吧,我可以解决这个问题!让我们编写一个 Java 程序,并放置一些逻辑来查找错误......”
我需要我的逻辑从“结果”中一次接收一个字符,并根据当前的表上下文应用我的逻辑来标记它是否应该存在...
但是!当我在:myLanguage = "Belarusian"
:
有人会认为这种语言与俄语非常相似,但结果的格式却完全不同,因为来自数据库:result = "U+002D\nU+0030\nU+0030..."
!
而且,还有另一种格式!
myLanguage = "Chinese"
:result = "#\nU+002D;U+002D;U+003D,U+004D,U+002D\nU+0030;U+0030;U+0030"
FWIW:charcodes 列是 CLOB 类型。
我知道 U+002D
是“-”而 U+0030
是“0”...
我目前的想法是:
1] 检查整个响应是 'щ' 格式还是 'U+0449` 格式('U+****' 是否用 ';'、',' 或 '\n' 分隔 - 我只是将它们视为独立字符)
一种。如果它是“简单的”,只需将字符发送到我的测试方法
湾如果是“hard one”,获取十六进制部分(0449),转换为十进制(1097)并转换为char(щ)
所以,我的问题是:
- “U+043E;U+006F,U+004D”格式是什么?
- 如果它是一个广泛使用的标准,Java 是否提供任何方法将这些字符串的整个字符串转换为字符数组?
解决方法
更新
“U+043E;U+006F,U+004D”是什么格式?
在 comment 中,OP 提供了指向 https://www.iana.org/domains/idn-tables/tables/academy_zh_1.0.txt 的链接,其中包含以下文本:
- 此表符合 RFC 3743 中指定的格式。
RFC 3743 可在 https://tools.ietf.org/html/rfc3743
找到如果它是一个广泛使用的标准,Java 是否提供任何方法将这些字符串的整个字符串转换为字符数组?
它不是一个广泛使用的标准,所以 Java 本身没有提供,但是使用正则表达式很容易转换为常规字符串,因此您可以正常处理字符串。
// Java 11+
static String decodeUnicode(String input) {
return Pattern.compile("U\\+[0-9A-F]{4,6}").matcher(input).replaceAll(mr ->
Character.toString(Integer.parseInt(mr.group().substring(2),16)));
}
// Java 9+
static String decodeUnicode(String input) {
return Pattern.compile("U\\+[0-9A-F]{4,6}").matcher(input).replaceAll(mr ->
new String(new int[] { Integer.parseInt(mr.group().substring(2),16) },1));
}
// Java 1.5+
static String decodeUnicode(String input) {
StringBuffer buf = new StringBuffer();
Matcher m = Pattern.compile("U\\+[0-9A-F]{4,6}").matcher(input);
while (m.find()) {
String hexString = m.group().substring(2);
int codePoint = Integer.parseInt(hexString,16);
String unicodeCharacter = new String(new int[] { codePoint },1);
m.appendReplacement(buf,unicodeCharacter);
}
return m.appendTail(buf).toString();
}
测试
System.out.println(decodeUnicode("#\nU+002D;U+002D;U+003D,U+004D,U+002D\nU+0030;U+0030;U+0030"));
输出
#
-;-;=,M,-
0;0;0
,
U+0000 是 Unicode 代码点的表示,格式定义为 in Apendix A of the Unicode Standard。这些数字只是表示的代码点的十六进制编码数字。由于历史原因,它们总是用 0
左填充至至少 4 位,但最长可达 6 位。
它主要不是作为一种机器可读的编码,而是作为一种人类可读的 Unicode 代码点表示,用于运行文本(即像这样的段落)。尤其要注意的是,这种格式没有能够将后面跟着一些数字的四字符数字与 5 位或 6 位数字区分开来。因此 U+123456
可以解释为 3 种不同的方式:U+1234
后跟文本 56
、U+12345
后跟文本 6
或 U+123456
。这使得它不适合自动替换和用作通用编码。
因此,在 Java 中没有将其解析为等效的 String
或类似内容的内置功能。
以下代码可用于将 单个 Unicode 代码点引用解析为 String
中的适当代码点:
public static String codePointToString(String input) {
if (!input.startsWith("U+")) {
throw new IllegalArgumentException("Malformed input,doesn't start with U+");
}
int codepoint = Integer.parseInt(input.substring(2),16);
if (codepoint < 0 || codepoint > Character.MAX_CODE_POINT) {
throw new IllegalArgumentException("Malformed input,codepoint value out of valid range: " + codepoint);
}
return Character.toString(codepoint);
}
(在 Java 11 之前,返回行需要使用 new String(new int[] { codepoint },1)
代替)。
如果您想将文本中表示的所有 Unicode 代码点替换为其实际文本(在某些情况下可能会使其不可读),您可以使用此方法(结合上述方法):
private static final Pattern PATTERN = Pattern.compile("U\\+[0-9A-Za-z]{4,6}");
public static String decodeCodePoints(String input) {
return PATTERN
.matcher(input)
.replaceAll(result -> codePointToString(result.group()));
}
,
实际上,我编写了一个名为 MgntUtils 的开源库,它有一个实用程序,可以为您提供很大帮助。您看到的代码是 unicode 序列,其中每个 U+XXXX 代表一个字符。库中的实用程序可以将任何语言的任何字符串(包括特殊字符)转换为 Unicode 序列,反之亦然。以下是其工作原理的示例:
result = "Hello World";
result = StringUnicodeEncoderDecoder.encodeStringToUnicodeSequence(result);
System.out.println(result);
result = StringUnicodeEncoderDecoder.decodeUnicodeSequenceToString(result);
System.out.println(result);
这段代码的输出是:
\u0048\u0065\u006c\u006c\u006f\u0020\u0057\u006f\u0072\u006c\u0064
Hello World
该库可以在 Maven Central 或 Github 找到它作为 maven 工件和源代码和 javadoc
这是 StringUnicodeEncoderDecoder 类的 javadoc
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。