这种格式是:“U+043E;U+006F,U+004D”某种编码标准,java 是否提供了标准库方法将其转换为字符?

如何解决这种格式是:“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 后跟文本 56U+12345 后跟文本 6U+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 CentralGithub 找到它作为 maven 工件和源代码和 javadoc

这是 StringUnicodeEncoderDecoder 类的 javadoc

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-