如何从java中的字符串中获取正确的阿拉伯字符(正确的形式)?

2023-12-22

我试图计算java中阿拉伯字符串中字符的宽度,但有时我无法获得正确的字符。如果您不知道阿拉伯字符可以根据它们在单词中的位置进行连接,并且每个变体都有不同的十六进制代码:https://en.wikipedia.org/wiki/Arabic_script_in_Unicode#:~:text=External%20links-,Contextual%20forms,-%5Bedit%5D https://en.wikipedia.org/wiki/Arabic_script_in_Unicode#:%7E:text=External%20links-,Contextual%20forms,-%5Bedit%5D

发生的事情是,假设我在这个字符中读到: Ê (十六进制值 FE95) 。现在,根据它在单词中出现的位置,它可以采取不同的形式(请参阅上下文链接,这是表中的第三个字母)。当它出现在单词的开头时,它应该看起来像:ﺗ(十六进制代码 FE97)。在我读取的字符串中,它显示为 ﺗ (十六进制代码 FE97),但是当我使用 string.charAt(index) 读取它时,我得到 Ê (十六进制值 FE95)。有谁知道如何用正确的十六进制值读取正确的字符?

编辑: 这里供参考的是字符串 ÍÍÀõك 。中间的字母都没有以正确的形式读入:

  • 第一个字母是我上面描述的那个
  • 第二个字母是字母 Í(十六进制 FEB5)。在单词中,它表示为 ﺸ(十六进制 FEB8),但当通过 string.charAt 读取时,它保存值 Í(十六进制 FEB5)
  • 第三个字母是 Ù(十六进制 FEA5)。在单词中,它表示为 ﺨ(十六进制 FEA8),但当通过 string.charAt 读取时,它保存值 Ù(十六进制 FEA5)

等等... 任何帮助将非常感激!


From 您链接的维基百科文章 https://en.wikipedia.org/wiki/Arabic_script_in_Unicode:

呈现形式的存在只是为了与旧标准兼容,目前不需要对文本进行编码。

换句话说,您应该只使用通用形式(即 0600–06FF 范围代码点),而不是 FE70–FEFF 代码点范围的表示形式。请注意,您的示例字符串 ФдЮиеك 仅由 06xx 个字符组成,至少是浏览器给我的。

如果您有 FE70–FEFF 字符的旧源,请不要尝试修复它们的顺序,而只需通过将字符串转换为规范形式来删除表示信息。例如。

String s = "\uFE97\uFE98\uFE97\uFE96\uFE98";
System.out.println(s);
s = Normalizer.normalize(s, Normalizer.Form.NFKD);
System.out.println(s);
System.out.println(s.chars().mapToObj(i -> String.format("\\u%04X", i))
    .collect(Collectors.joining("", "\"", "\"")));

打印

ﺗﺘﺗﺖﺘ
تتتتت
"\u062A\u062A\u062A\u062A\u062A"

该示例的源字符串故意弄乱了表示形式字符,以显示如何仅获取没有表示信息、仅由通用 U+062A 字符的重复组成的字符串来解决问题。换句话说,通用字符串被正确打印。

这种处理是通过字体完成的,该功能称为字形整形。我们可以看到它的实际效果,例如和

Font font = new Font("DejaVu Sans", 0, 48); // or Droid Sans Arabic
FontRenderContext frc = new FontRenderContext(null, true, false);

String s = "\u062A\u062A\u062A";
System.out.println(s);

if(font.canDisplayUpTo(s) >= 0) {
    System.out.println("can't display string");
    System.exit(0);
}
GlyphVector g = font.layoutGlyphVector(frc,
    s.toCharArray(), 0, s.length(), Font.LAYOUT_RIGHT_TO_LEFT);

Rectangle r = g.getPixelBounds(frc, 0, 0);
System.out.println("Total width " + r.width);
for(int i = 0, n = g.getNumGlyphs(); i < n; i++) {
    int chPos = g.getGlyphCharIndex(i);
    System.out.printf("%2d (U+%04X) glyph code %4d, width %.0f%n",
        chPos,(int)s.charAt(chPos),g.getGlyphCode(i),g.getGlyphMetrics(i).getAdvance());
}
BufferedImage bi = new BufferedImage(r.width, r.height, BufferedImage.TYPE_BYTE_BINARY);
Graphics2D gfx = bi.createGraphics();
//System.out.println(r);
gfx.drawGlyphVector(g, -r.x, -r.y);
gfx.dispose();
for(int line = 0, nLines = r.height; line < nLines; line++) {
    for(int ch = 0, nChars = r.width; ch < nChars; ch++) {
        System.out.print((bi.getRGB(ch, line) & 0xff) > 0? 'X': ' ');
    }
    System.out.println();
}
System.out.println();

在线尝试一下! https://tio.run/##hVRtb9owEP7OrzhFYjgiDaiqpmm0m6B0HVLXVpRWRduETOIkZsFBtlOCJn47OwdoE0i1fEjse3nu7vHjzOgLPZn5fzYbPl8kUsMMDS5davdbInSndmi9lnQRcU@d9o99Q@ZpKsKYHbsCBMsRh0z4TF7iimX6nbjreLWInhAskccRfE5D5vbSIGCS@QOz69RqNS@mSoGpcJXR@SJm8LcG@CzSacw9UJpq/Lwk3Ic55YI8aMlF@PM3UBkqexdsHgMBpg24AMGW@Z5YfTajTyk8UKEsB9oOnH2yO9BqQSKhLw2qcUFX0in3SlilgSGQXgG35CMijWMHtEyZAwGNFbNxsD3Utl9QmG39StsfT7vFt9V5C1wpzeZukmp3gSk6FkQVgXhAcpI9KvpcLWK6elyMEoyBLxfQLjLxDpqFmQ0N/jYZmTWNWXanKo9lXJN2wbd@XRUOGUKcKm8KAbFUwUWQMKeErFydXEZUdqWkK2Lnh6HcmIlQR2ZreHVvuuO7x9FkOLj@PpqM7iY3V99GRRJelQoSS4duyPQ9z1jcS1Lhq7yowS12XsXEKNE0hiX3dQQWNEG6@bqQFeAIGAwcyyCg2Fe7Tef5lIqgjDicg8BPs3lIv0n1ovtE7fPyJDP@AJWTEV5N@2uTAbHqpz6Qx2a9ffZsQ2jSwUt8BvUz39m1XnfbQV1YZZ7Nk5d2zAC2cj1Duia5zXYK3SAaNlKw/GCoCU@h0Zi6/gsVHiN2pQxKFxmmfHc7Smay49VBgiPGw0g75QB3NL6/mvTGI3wNbrvDcaHU2w8LwiBD@Cl3PcmoZnsPKUS3WhXnLAsBiOH6ki6LGg0dOJFulr9Xh7F4TRLFSIUmYi7YThY3uDRnvJ@vs3We7zzb7bE89khetMMxytji5IR1jOd8ZzabY4gq1RCCHOHJDa97eNxOXtyGD9DOggB/E9D@Co3nxmdoQONAf@v//TwqNfB@3Lq23mz@AQ

تتت
Total width 70
 2 (U+062A) glyph code 5261, width 47
 1 (U+062A) glyph code 5263, width 14
 0 (U+062A) glyph code 5262, width 13
                                               XX    XX      XX    XX 
                                              XXXX  XXXX    XXXX  XXXX
                                              XXXX  XXXX    XXXX  XXXX
                                              XXXX  XXXX    XXXX  XXXX
                                                                      
              XX    XX                                                
             XXXX  XXXX                                               
             XXXX  XXXX                                               
             XXXX  XXXX           XXXX                                
                                  XXXX                                
 XXXX                             XXXXX          XXXX          XXXX   
 XXXX                             XXXXX          XXXX          XXXX   
XXXXX                             XXXXX          XXXX          XXXX   
XXXX                              XXXXX          XXXX          XXXX   
XXXX                              XXXXX          XXXX          XXXX   
XXXX                             XXXXXX          XXXX          XXXX   
XXXXX                          XXXXXXXX          XXXX          XXXX   
XXXXX                        XXXXXXXXXXX        XXXXXX        XXXXX   
 XXXXXX                    XXXXXXXXXXXXX        XXXXXX        XXXXX   
 XXXXXXXX              XXXXXXXXXXX  XXXXXX    XXXXXXXXXX    XXXXXX    
  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX    
   XXXXXXXXXXXXXXXXXXXXXXXXXXXX      XXXXXXXXXXXXXXXXXXXXXXXXXXXX     
     XXXXXXXXXXXXXXXXXXXXXXX          XXXXXXXXXXXX  XXXXXXXXXXXX      
        XXXXXXXXXXXXXXXX                XXXXXXXXX    XXXXXXXXXX       

请注意,实际的字形数量完全取决于特定的字体。例如,某些字体将中间的 Ê 字符映射到与最后一个字符相同的字形 - 纯粹的风格选择。

该程序仅用于演示相同的代码点(在本例中,char就足够了)可能会映射到不同的字体特定字形。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何从java中的字符串中获取正确的阿拉伯字符(正确的形式)? 的相关文章

  • 在 libgdx 中批处理多维数据集时出现问题

    我正在尝试开发一款游戏 在屏幕上渲染多达 300 个立方体 为每个多维数据集创建新的 modelInstance 时 modelBatch 的性能非常糟糕 据我所知 没有 3d 批处理可以将所有立方体批处理到一次绘制调用 所以我拼命地尝试以
  • SharePoint 2010 Web 服务上的 Java JBoss 401 错误

    我的代码在 Eclipse IDE 中测试时运行成功 我正在使用生成的 Copy wsdl 通过 Web 服务连接到 MS SharePoint 2010 当我在 JBoss 服务器上部署代码 运行 Adob e LifeCycle 时 我
  • Google API - 重定向 URI 不匹配错误

    我正在我的网络应用程序上实现 google 登录 我通过参考this尝试过link https developers google com web signin server side flow 我的 google 登录按钮如下 div s
  • 从 Windows Batch (cmd.exe) 中的文件读取环境变量

    我正在尝试从批处理文件中读取变量 以便稍后在批处理脚本 Java 启动器 中使用 理想情况下 我希望所有平台 Unix Windows 上的设置文件都具有相同的格式 并且也是有效的 Java 属性文件 也就是说 它应该看起来像这样 sett
  • 在 Java 中将字符串复制到文件的开头

    我想将一个字符串写入文件的开头 我该怎么做 我根本不知道如何添加字符串 这就是我到目前为止所做的 public static void prepend String filename String data throws IOExcepti
  • 如何用 Java 制作 Windows 7 工具提示

    我一直在网上到处寻找 但没有找到这个小问题的答案 在 Windows 7 中 我认为在 Vista 中 您有一个漂亮的圆形银色工具提示 它看起来比旧的黄色盒装蹩脚工具提示要好得多 下面的 How do I make a Windows 7
  • 在 Selenium Grid 中注册 PhantomJS 节点时出错

    我有以下问题 我成功启动了 Selenium Grid hub java jar selenium server standalone 2 53 0 jar role hub 之后我尝试使用以下命令启动 PhantomJS 节点 phant
  • xclock 工作,X11 DISPLAY 设置但仍然 java.awt.HeadlessException:

    获取 java awt HeadlessException 似乎是一个非常常见的问题 并且 中已经讨论过 以下问题 没有 X11 DISPLAY 变量 这是什么意思 https stackoverflow com questions 662
  • 错误:类 kotlin.reflect.jvm.internal.FunctionCaller$FieldSetter

    我已尝试一切方法来消除此错误 但它不断出现 Class kotlin reflect jvm internal FunctionCaller FieldSetter can not access a member of class com
  • 如何查找类路径中具有指定名称的所有资源?

    我想列出类路径中具有特定名称的所有文件 我预计会发生多次 因此Class getResource String 不管用 基本上 我必须识别类路径中任何位置具有特定名称 例如 xyz properties 的所有文件 然后累积读取其中的元数据
  • 在Linux中执行jar文件[关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我创建了一个可执行的 Java jar 文件 也就是说 我将 java 程序正确打包到 jar 文件中 包括 META INF MANIFEST 文件
  • 何时对字符串文字使用 intern()

    我看到很多这样的遗留代码 class A public static final String CONSTANT value intern 我看不出使用 intern 的任何原因 因为在 Javadoc 中可以读到 所有文字字符串和字符串值
  • CXF 增加连接池大小而不更改 http.maxConnections

    最近我被要求将 CXF 配置为与我们旧的 XFire 服务相同的参数 这些参数之一是Keep Alive timeout 60 max 20 然而 我做了一些研究 看来 CXF 使用 JVMHttpURLConnection引擎盖下的对象
  • 枚举

    我试图拥有一组扩展通用接口的枚举 例如 interface Fooable void someCommonMethod enum E1 implements Fooable some enumuerations and a definiti
  • 如何在 Windows 上使用 Java Hotspot JVM 禁用小型转储 (mdmp) 文件生成

    目前 我有一个已部署的可执行 jar 文件 该文件在崩溃时会创建大型 7 Gb 小型转储文件 我想要一个导致崩溃原因的文本表示 而不是 JVM 状态的二进制文件 我尝试使用中找到的信息这个 CodeRanch 帖子 http www cod
  • 解析整数集的字符串并列出间隔

    I have 2 5 7 9 12 string 我想从中获取 2 5 7 8 9 12 列表 python中有没有内置的函数 Thanks UPD 我想 直接的答案是No 不管怎样 谢谢你的 片段 使用一个 建议者斯文 马尔纳克 s 2
  • 不幸的是 Project_Name 已停止

    我有一个简单的应用程序 您可以在文本视图中输入文本并按提交 它会在另一个活动中显示文本 然而 当我按下提交时 给我消息 不幸的是 发送已停止 我查看了SO上的其他线程 但是不幸的是 myfirstproject 在 java 中停止工作错误
  • 如何使用现代.fxml和controller.java在javafx 2.x中制作自动完成组合框[重复]

    这个问题在这里已经有答案了 如何使用现代 fxml 和controller java 在 javafx 2 x 中制作一个类似的自动完成组合框 就像制作这个一样 http blog ngopal com np 2011 07 04 auto
  • 如何在不下载子项的情况下从 Firebase 获取子项密钥?

    我有一个 Firebase 数据库 其中的节点 items 有很多子项 我想导入子项键的列表 由于每个子项都包含相当多我对此不感兴趣的数据 因此我想仅下载子项密钥 以最大程度地减少传输的数据量 为了便于说明 假设我有以下数据结构 然后我想获
  • 如何读取FTL文件中的JSONArray?

    我在我的 Java 文件中硬编码了以下 JSON 对象 JSONObject notificationInfoJson new JSONObject notificationInfoJson put title Payment Receiv

随机推荐