Java 如何获取Unicode字符的基指针?

Java 如何获取Unicode字符的基指针?,java,unicode,Java,Unicode,目前我有“codePointAt”,它从字符串返回字符的代码点。 是否有任何API或其他方法来获取当前字符的基指针 public class Testclass { public static void main(String[] args) { String unicodeString = "कागज़"; int currentPoint = unicodeString.codePointAt(0); // Now currentP

目前我有“codePointAt”,它从字符串返回字符的代码点。 是否有任何API或其他方法来获取当前字符的基指针

public class Testclass {

    public static void main(String[] args) {

        String unicodeString = "कागज़";
        int currentPoint = unicodeString.codePointAt(0);

        // Now currentPoint = 0x0915
        // I need currentPoint = 0x0900
    }
}
注意#我无法通过加法/减法创建基指针,因为不同语言的基点从不同的1/10位值开始。例如

亚美尼亚语-0530-058F-基指针0x0530(十位值)
Devanagari-0900-097F-基指针0x0900(百位值)

目前,我正在使用if-else块获取基指针,这不是动态的,也是冗长的方法:-(

int基指针;

如果(currentPoint>0x600&¤tPoint 0x900&¤tPoint,您可以使用位操作来查找基本指针,如下所示:

 switch (codePoint & 0xffffff00) {
   case 0x0600: // Arabic
   case 0x0900: // Devnagri, though you might need to check it is below 0x97F
   case 0x0000: // Latin
   default:     // Something else
 }
啊,对不起,我认为亚美尼亚语需要进一步处理,但希望总体思路适用于大多数语言

public static int baseCodePoint(int codePoint) {
  switch (codePoint & 0xffffff00) {
    case 0x0900: if (codePoint < 0x0980) return 0x0900;
    case 0x0500: if (codePoint >= 0x0530 && codePoint <= 0x058F) return 0x0530;
    // case ...: other bases where it is not the real base
    // Handling regular base pointers
    default: return codePoint & 0xffffff00;
  }
}
公共静态int-baseCodePoint(int-codePoint){
开关(代码点和0xFFFF00){
案例0x0900:if(代码点<0x0980)返回0x0900;

案例0x0500:如果(代码点>=0x0530&&codePoint,您可以将每种语言的开始/结束位置设置为
SortedMap
s,并检查代码点:

 private static final SortedSet<Integer, Integer> startToBase = new TreeMap<>();
 private static final SortedSet<Integer, Integer> endToBase = TreeMap<>();
 static {
   // Fill the SortedMaps:
   // latin
   startToBase.put(0, 0);
   endToBase.put(0x00ff, 0);
   // ...
 }
 // Or load this from a web service, table or anything you find comfortable

 public static final int baseCodePoint(int codePoint) {
   // The codePoint should be inserted here (after)
   int baseFromStart = startToBase.get(startToBase.headMap(codePoint + 1).lastKey());
   // the code point should be inserted here (before).
   int baseFromEnd   = endToBase.get(endToBAse.tailMap(codePoint).firstKey());
   if (baseFromStart == baseFromEnd) {
     return baseFromStart;
   }
   throw new IllegalArgumentException(codePoint + " is unknown.");
 }
private static final SortedSet startToBase=new TreeMap();
私有静态最终分类集endToBase=TreeMap();
静止的{
//填写分类地图:
//拉丁语
startToBase.put(0,0);
endToBase.put(0x00ff,0);
// ...
}
//或者从web服务、表或任何您认为合适的地方加载此文件
公共静态最终整数基码点(整数码点){
//代码点应插入此处(之后)
int baseFromStart=startToBase.get(startToBase.headMap(codePoint+1.lastKey());
//应在此处(之前)插入代码点。
int baseFromEnd=endToBase.get(endToBase.tailMap(codePoint.firstKey());
if(baseFromStart==baseFromEnd){
返回baseFromStart;
}
抛出新的IllegalArgumentException(代码点+“未知”);
}

好的,在考虑了一下这一点之后,这里有一种使用Java API的方法。它由三部分组成:

  • 将中不可访问的块基表重新生成为
    Map
  • 用于查找给定代码点的块名
  • 使用
    映射
    查找给定块名的Unicode块基
  • 请注意,在我的机器上,在大约10-15毫秒的时间内,重新生成块基表的速度相对较慢,因此最好生成一次并重新使用。我保留了基本的计时代码

    private static final int SUPPLEMENTARY_PRIVATE_USE_AREA_A_BASE = 0x0F0000;
    private static final int SUPPLEMENTARY_PRIVATE_USE_AREA_B_BASE = 0x100000;
    
    private static final Character.UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_A =
        Character.UnicodeBlock.of(SUPPLEMENTARY_PRIVATE_USE_AREA_A_BASE);
    private static final Character.UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_B =
        Character.UnicodeBlock.of(SUPPLEMENTARY_PRIVATE_USE_AREA_B_BASE);
    
    public static Map<Character.UnicodeBlock, Integer> makeUnicodeBlockBaseMap() {
      long startNanos = System.nanoTime();
      Map<Character.UnicodeBlock, Integer> unicodeBases = new HashMap<>();
      // Unicode blocks start on 16 (0x10) byte boundaries.
      for (int cp = 0x00000; cp < SUPPLEMENTARY_PRIVATE_USE_AREA_A_BASE; cp += 0x10) {
        Character.UnicodeBlock ucb = Character.UnicodeBlock.of(cp);
        if (ucb != null) {
          unicodeBases.putIfAbsent(ucb, cp);
        }
      }
      // These blocks are huge, so add them manually.
      unicodeBases.put(SUPPLEMENTARY_PRIVATE_USE_AREA_A, SUPPLEMENTARY_PRIVATE_USE_AREA_A_BASE);
      unicodeBases.put(SUPPLEMENTARY_PRIVATE_USE_AREA_B, SUPPLEMENTARY_PRIVATE_USE_AREA_B_BASE);
      long endNanos = System.nanoTime();
      System.out.format("Total time = %.3f s%n", (endNanos - startNanos) / 1e9);
      return unicodeBases;
    }
    
    public static void main(String[] args) {
      Map<Character.UnicodeBlock, Integer> unicodeBlockBases = makeUnicodeBlockBaseMap();
    
      String unicodeString = "कागज़";
      int currentPoint = unicodeString.codePointAt(0);
    
      Character.UnicodeBlock ucb = Character.UnicodeBlock.of(currentPoint);
      System.out.println(ucb);                                   // DEVANAGARI
      System.out.format("0x%04X%n", unicodeBlockBases.get(ucb)); // 0x0900
    }
    
    private static final int SUPPLEMENTARY\u private\u USE\u AREA\u A\u BASE=0x0F0000;
    专用静态最终整数补充\专用\使用\面积\基数=0x100000;
    private static final Character.UnicodeBlock补充_private_USE_AREA_A=
    字符.UnicodeBlock.of(补充\私人\使用\区域\基地);
    private static final Character.UnicodeBlock补充_private_USE_AREA_B=
    字符.UnicodeBlock.of(补充\私人\使用\区域\基地);
    公共静态映射makeUnicodeBlockBaseMap(){
    long startNanos=System.nanoTime();
    Map=newhashmap();
    //Unicode块从16(0x10)字节边界开始。
    对于(int cp=0x00000;cp<辅助\u专用\u使用\u区域\u基地;cp+=0x10){
    Character.UnicodeBlock ucb=Character.UnicodeBlock.of(cp);
    如果(ucb!=null){
    独角兽。putIfAbsent(ucb,cp);
    }
    }
    //这些块很大,所以手动添加它们。
    unicodeBases.put(辅助专用区、辅助专用区、辅助基地);
    unicodeBases.put(补充用地、补充用地);
    long-endNanos=System.nanoTime();
    System.out.format(“总时间=%.3f s%n”,(endNanos-startNanos)/1e9);
    退换货;
    }
    公共静态void main(字符串[]args){
    Map unicodeBlockBases=makeUnicodeBlockBaseMap();
    字符串解析=”कागज़";
    int currentPoint=unicodeString.codepoint(0);
    Character.UnicodeBlock ucb=Character.UnicodeBlock.of(currentPoint);
    System.out.println(ucb);//DEVANAGARI
    System.out.format(“0x%04X%n”,unicodeblockbase.get(ucb));//0x0900
    }
    
    多亏了Gábor Bakos的灵感,我做到了这一点:

    TreeMap<Integer, Integer> languageCodePoints = new TreeMap<>();
    languageCodePoints.put(0x0020, 0x007E);
    languageCodePoints.put(0x00A0, 0x00FF);
    languageCodePoints.put(0x0100, 0x017F);
    languageCodePoints.put(0x0900, 0x097F); // Devanagri  
    
    // So on for all other languages, referred ISO/IEC 10646:2010 
    // for code points of present languages
    
    现在“startDepoint=0x900”是我真正需要的。我认为这是一个非常简单的方法。:-p
    有一件事是,我必须为新的语言条目维护“languageCodePoints”树状图,但要比switch/if-else好得多


    感谢大家的支持。:-)

    我认为亚美尼亚语/德瓦纳加里语的问题是这个问题的核心。也许一个比特模式列表,先使用较短的比特模式或类似的东西可能会有用?Hi@GáborBakos谢谢,但它不会处理许多语言。我也不想为所有语言编写if-else/switch case。我目前使用的是一个st自动进近:-(嗯,后一个选项已经可以处理拉丁语、西里尔语、阿拉伯语、藏语和更多的语言。@GáborBakos,但您提供的解决方案是使用switch case,我必须为其维护一个不是动态方法的案例表。因此它不满足要求。感谢您提供了另一种方法,但请理解我正在寻求一种动态方法。如果,在任何情况下,我必须以任何方式创建语言代码的数据库/存储,那么解决方案是没有帮助的。:-(头部映射/尾部映射部分可能会出现一个接一个的错误。在这种情况下,您应该向unicode consortium投诉,因为它创建了这样的代码。)说真的,我认为有这样的数据库,你只需要适当地解析它就可以了。呵呵:-D,我想的是创建一个库,然后发布给其他人使用,因为我找不到任何库。:-D感谢你的启发。我已经创建了一个树形图,并获得了基本代码点。唯一的是静态方法,但是这比我想象的要好得多
    TreeMap<Integer, Integer> languageCodePoints = new TreeMap<>();
    languageCodePoints.put(0x0020, 0x007E);
    languageCodePoints.put(0x00A0, 0x00FF);
    languageCodePoints.put(0x0100, 0x017F);
    languageCodePoints.put(0x0900, 0x097F); // Devanagri  
    
    // So on for all other languages, referred ISO/IEC 10646:2010 
    // for code points of present languages
    
    String unicodeString = "कागज़";
    int currentPoint = unicodeString.codePointAt(0);
    int startCodePoint = languageCodePoints.floorKey(currentPoint);