Java 如何获取Unicode字符的基指针?
目前我有“codePointAt”,它从字符串返回字符的代码点。 是否有任何API或其他方法来获取当前字符的基指针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
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);