Character.getType(int codePoint)
返回一个整数,我无法找到方法
获取unicode类别名称,例如" Lu"或者" Cn",其中。
我想要的是一个方法,如Character.getCategoryTypeName(int codePoint)
,返回表示类型的字符串。
类别名称在常量注释中,和 一种方法是为返回的类型编写一个switch case,然后手动编码类型名称,如下所示:
我最初的计划是这样的:
for (int i = 0; i <= 0x10FFFF; i++) {
switch (Character.getType(i)) {
// General category "Sc" in the Unicode specification.
// public static final byte CURRENCY_SYMBOL = 26;
case Character.CURRENCY_SYMBOL:
map.put(i, "Sc");
break;
....
}
}
然而,这将是非常乏味的。是否有自动方式或库来完成任务?
答案 0 :(得分:2)
正如所评论的,目前似乎没有与 Java 捆绑的此类功能。作为 Marcono1234 commented,a feature-request is on the books 但尚未实施。
自我注意:如果我在会议上与Brian Goetz或Mark Reinhold擦肩而过,请要求/恳求/恳求他们对与{{的工作进行重大改进3}} 和 code points 在 Java 中。
我想出了几种方法来为 Unicode 定义的 30 个“一般类别”项目中的每一个生成您想要的两个字母的名称。 (这个由两个字母组成的名称在 Unicode 规范中称为“别名”。)我的一个实现只是为每个别名硬编码了 switch
。另一个更复杂,定义了几个枚举。
这两个实现都是我创建的,只是作为练习。我没有在生产中使用它们。我并不是说它们是最好的路线,但希望它们可能会被证明是有用的,或者至少能激励其他人做出更好的努力。
在 Java 14+ 中,对 Unicode 类上定义的每个“通用类别”常量使用 switch
表达式。如果不熟悉,请参阅Character
。
public String unicodeGeneralCategoryAliasForCodePoint ( int codePoint ) {
return switch ( Character.getType( codePoint ) ) {
// L, Letter
case Character.UPPERCASE_LETTER -> "Lu";
case Character.LOWERCASE_LETTER -> "Ll";
case Character.TITLECASE_LETTER -> "Lt";
case Character.MODIFIER_LETTER -> "Lm";
case Character.OTHER_LETTER -> "Lo";
// M, Mark
case Character.NON_SPACING_MARK -> "Mn";
case Character.COMBINING_SPACING_MARK -> "Mc";
case Character.ENCLOSING_MARK -> "Me";
// N, Number
case Character.DECIMAL_DIGIT_NUMBER -> "Nd";
case Character.LETTER_NUMBER -> "Nl";
case Character.OTHER_NUMBER -> "No";
// P, Punctuation
case Character.CONNECTOR_PUNCTUATION -> "Pc";
case Character.DASH_PUNCTUATION -> "Pd";
case Character.START_PUNCTUATION -> "Ps";
case Character.END_PUNCTUATION -> "Pe";
case Character.INITIAL_QUOTE_PUNCTUATION -> "Pi";
case Character.FINAL_QUOTE_PUNCTUATION -> "Pf";
case Character.OTHER_PUNCTUATION -> "Po";
// S, Symbol
case Character.MATH_SYMBOL -> "Sm";
case Character.CURRENCY_SYMBOL -> "Sc";
case Character.MODIFIER_SYMBOL -> "Sk";
case Character.OTHER_SYMBOL -> "So";
// Z, Separator
case Character.SPACE_SEPARATOR -> "Zs";
case Character.LINE_SEPARATOR -> "Zl";
case Character.PARAGRAPH_SEPARATOR -> "Zp";
// C, Other
case Character.CONTROL -> "Cc";
case Character.FORMAT -> "Cf";
case Character.SURROGATE -> "Cs";
case Character.PRIVATE_USE -> "Co";
case Character.UNASSIGNED -> "Cn";
default -> "ERROR - Unexpected General Category type for code point " + codePoint + ". Message # 5d44e5fd-d60e-4b02-9431-ad57c56657f5.";
};
}
用法:
String alias = x.unicodeGeneralCategoryAliasForCodePoint( 65 );
<块引用>
陆
在这种替代方法中,我定义了一对枚举:
UnicodeGeneralCategory
UnicodeMajorClass
UnicodeGeneralCategory
的对象分组为 Unicode 规范定义的组:字母、标记、数字、标点、符号、分隔符等。最后一个“其他”值得注意,因为它涵盖了不可打印的“控制”字符以及未分配给任何字符的绝大多数代码点。当 this Wikipedia page 时,我们想跳过这些。UnicodeGeneralCategory
中我的枚举对象的名称是从 looping over all the possible code points 类上声明的常量子集复制的,该类的描述以短语“一般类别”开头。这些常量名称与官方的 Unicode 名称有些不同,但足够接近。我按照 Unicode 规范中列出的顺序定义了这些。
package work.basil.unicode.category;
import java.util.Arrays;
import java.util.Optional;
// For more info about Unicode General Category, see section 4.5 of the Unicode 13.0 spec, pages 170-172.
// https://www.unicode.org/versions/Unicode13.0.0/ch04.pdf
public enum UnicodeGeneralCategory {
// See Wikipedia page list the General Category values defined in Unicode 13.
// L, Letter
UPPERCASE_LETTER( Character.UPPERCASE_LETTER , "Lu" , "Letter" , "uppercase" ),
LOWERCASE_LETTER( Character.LOWERCASE_LETTER , "Ll" , "Letter" , "lowercase" ),
TITLECASE_LETTER( Character.TITLECASE_LETTER , "Lt" , "Letter" , "titlecase" ),
MODIFIER_LETTER( Character.MODIFIER_LETTER , "Lm" , "Letter" , "modifier" ),
OTHER_LETTER( Character.OTHER_LETTER , "Lo" , "Letter" , "other" ),
// M, Mark
NON_SPACING_MARK( Character.NON_SPACING_MARK , "Mn" , "Mark" , "nonspacing" ),
COMBINING_SPACING_MARK( Character.COMBINING_SPACING_MARK , "Mc" , "Mark" , "spacing combining" ),
ENCLOSING_MARK( Character.ENCLOSING_MARK , "Me" , "Mark" , "enclosing" ),
// N, Number
DECIMAL_DIGIT_NUMBER( Character.DECIMAL_DIGIT_NUMBER , "Nd" , "Number" , "decimal digit" ),
LETTER_NUMBER( Character.LETTER_NUMBER , "Nl" , "Number" , "letter" ),
OTHER_NUMBER( Character.OTHER_NUMBER , "No" , "Number" , "other" ),
// P, Punctuation
CONNECTOR_PUNCTUATION( Character.CONNECTOR_PUNCTUATION , "Pc" , "Punctuation" , "connector" ),
DASH_PUNCTUATION( Character.DASH_PUNCTUATION , "Pd" , "Punctuation" , "dash" ),
START_PUNCTUATION( Character.START_PUNCTUATION , "Ps" , "Punctuation" , "open" ),
END_PUNCTUATION( Character.END_PUNCTUATION , "Pe" , "Punctuation" , "close" ),
INITIAL_QUOTE_PUNCTUATION( Character.INITIAL_QUOTE_PUNCTUATION , "Pi" , "Punctuation" , "initial quote" ),
FINAL_QUOTE_PUNCTUATION( Character.FINAL_QUOTE_PUNCTUATION , "Pf" , "Puntuation" , "final quote" ),
OTHER_PUNCTUATION( Character.OTHER_PUNCTUATION , "Po" , "Punctuation" , "other" ),
// S, Symbol
MATH_SYMBOL( Character.MATH_SYMBOL , "Sm" , "Symbol" , "math" ),
CURRENCY_SYMBOL( Character.CURRENCY_SYMBOL , "Sc" , "Symbol" , "currency" ),
MODIFIER_SYMBOL( Character.MODIFIER_SYMBOL , "Sk" , "Symbol" , "modifier" ),
OTHER_SYMBOL( Character.OTHER_SYMBOL , "So" , "Symbol" , "other" ),
// Z, Separator
SPACE_SEPARATOR( Character.SPACE_SEPARATOR , "Zs" , "Separator" , "space" ),
LINE_SEPARATOR( Character.LINE_SEPARATOR , "Zl" , "Separator" , "line" ),
PARAGRAPH_SEPARATOR( Character.PARAGRAPH_SEPARATOR , "Zp" , "Separator" , "paragraph" ),
// C, Other
CONTROL( Character.CONTROL , "Cc" , "Other" , "control" ),
FORMAT( Character.FORMAT , "Cf" , "Other" , "format" ),
SURROGATE( Character.SURROGATE , "Cs" , "Other" , "surrogate" ),
PRIVATE_USE( Character.PRIVATE_USE , "Co" , "Other" , "private use" ),
UNASSIGNED( Character.UNASSIGNED , "Cn" , "Other" , "not assigned" );
// Fields.
private byte characterClassConstantForGeneralCategory;
private String alias, major, minor;
// Constructor.
UnicodeGeneralCategory ( byte characterClassConstantForGeneralCategory , String alias , String major , String minor ) {
this.characterClassConstantForGeneralCategory = characterClassConstantForGeneralCategory;
this.alias = alias;
this.major = major;
this.minor = minor;
}
public static UnicodeGeneralCategory forCodePoint ( int codePoint ) {
if ( ! Character.isValidCodePoint( codePoint ) ) {
throw new IllegalArgumentException( "Code point " + codePoint + " is invalid. Must be within 0 to U+10FFFF ( 1,114,111 ) inclusive." );
}
Optional < UnicodeGeneralCategory > optionalUnicodeGeneralCategory = Arrays.stream( UnicodeGeneralCategory.values() ).filter( category -> category.characterClassConstantForGeneralCategory == Character.getType( codePoint ) ).findAny();
if ( optionalUnicodeGeneralCategory.isEmpty() ) {
throw new IllegalStateException( "No general category defined in this enum matching `Character.getType( codePoint )`: " + Character.getType( codePoint ) );
} else {
return optionalUnicodeGeneralCategory.get();
}
}
public static UnicodeGeneralCategory forAlias ( String abbrev ) {
Optional < UnicodeGeneralCategory > optionalUnicodeGeneralCategory = Arrays.stream( UnicodeGeneralCategory.values() ).filter( category -> category.alias == abbrev ).findAny();
if ( optionalUnicodeGeneralCategory.isEmpty() ) {
throw new IllegalArgumentException( "No general category defined in this enum for abbreviation " + abbrev );
} else {
return optionalUnicodeGeneralCategory.get();
}
}
// Getters
public String getAlias () {
return this.alias;
}
public String getMajor () {
return this.major;
}
public String getMinor () {
return this.minor;
}
public byte getCharacterClassConstant () {
return this.characterClassConstantForGeneralCategory;
}
public String getDisplayName () {
return this.alias + " – " + this.major + ", " + this.minor;
}
}
……和……
package work.basil.unicode.category;
import java.util.EnumSet;
import java.util.Set;
public enum UnicodeMajorClass {
L_Letter( "L" , "Letter" , EnumSet.of( UnicodeGeneralCategory.UPPERCASE_LETTER , UnicodeGeneralCategory.LOWERCASE_LETTER , UnicodeGeneralCategory.TITLECASE_LETTER , UnicodeGeneralCategory.MODIFIER_LETTER , UnicodeGeneralCategory.OTHER_LETTER ) ),
M_MARK( "M" , "Mark" , EnumSet.of( UnicodeGeneralCategory.NON_SPACING_MARK , UnicodeGeneralCategory.COMBINING_SPACING_MARK , UnicodeGeneralCategory.ENCLOSING_MARK ) ),
N_NUMBER( "N" , "Number" , EnumSet.of( UnicodeGeneralCategory.DECIMAL_DIGIT_NUMBER , UnicodeGeneralCategory.LETTER_NUMBER , UnicodeGeneralCategory.OTHER_LETTER ) ),
P_PUNCTUATION( "P" , "Punctuation" , EnumSet.of( UnicodeGeneralCategory.CONNECTOR_PUNCTUATION , UnicodeGeneralCategory.DASH_PUNCTUATION , UnicodeGeneralCategory.START_PUNCTUATION , UnicodeGeneralCategory.END_PUNCTUATION , UnicodeGeneralCategory.INITIAL_QUOTE_PUNCTUATION , UnicodeGeneralCategory.FINAL_QUOTE_PUNCTUATION , UnicodeGeneralCategory.OTHER_PUNCTUATION ) ),
S_SYMBOL( "S" , "Symbol" , EnumSet.of( UnicodeGeneralCategory.MATH_SYMBOL , UnicodeGeneralCategory.CURRENCY_SYMBOL , UnicodeGeneralCategory.MODIFIER_SYMBOL , UnicodeGeneralCategory.OTHER_SYMBOL ) ),
Z_SEPARATOR( "Z" , "Separator" , EnumSet.of( UnicodeGeneralCategory.SPACE_SEPARATOR , UnicodeGeneralCategory.LINE_SEPARATOR , UnicodeGeneralCategory.PARAGRAPH_SEPARATOR ) ),
C_OTHER( "C" , "Other" , EnumSet.of( UnicodeGeneralCategory.CONTROL , UnicodeGeneralCategory.FORMAT , UnicodeGeneralCategory.SURROGATE , UnicodeGeneralCategory.PRIVATE_USE , UnicodeGeneralCategory.UNASSIGNED ) );
private String alias;
private String name;
private Set < UnicodeGeneralCategory > categories;
UnicodeMajorClass ( String alias , String name , Set < UnicodeGeneralCategory > categories ) {
this.alias = alias;
this.name = name;
this.categories = categories;
}
public String getAlias () {
return alias;
}
public String getName () {
return name;
}
public Set < UnicodeGeneralCategory > getCategories () {
return categories;
}
public String getDisplayName () {
return this.alias + " – " + this.name;
}
public boolean coversCodePoint ( int codePoint ) {
return this.getCategories().contains( UnicodeGeneralCategory.forCodePoint( codePoint ) );
}
}
用法:
UnicodeGeneralCategory.forCodePoint( yourCodePointGoesHere ).getAlias()
是您在问题顶部提出的要求。UnicodeMajorClass.C_OTHER.coversCodePoint( codePoint )
跳过那些讨厌的不可打印/未分配的代码点。此外,要获取由代码点编号表示的单个字符的 String
,请调用 Character.toString( codePoint )
。
我们可以使用这两个枚举来报告所有代码点。
package work.basil.text;
import work.basil.unicode.category.UnicodeMajorClass;
public class DumpCharacters {
public static void main ( String[] args ) {
System.out.println( "INFO - Demo starting. " );
for ( int codePoint = 0 ; codePoint <= Character.MAX_CODE_POINT ; codePoint++ ) {
if ( Character.isValidCodePoint( codePoint ) ) // If code point is valid.
{
if ( UnicodeMajorClass.C_OTHER.coversCodePoint( codePoint ) ) // If control character.
{
// No code needed. Skip over this code point as it is not a printable character.
} else {
System.out.println( codePoint + " code point is named: " + Character.getName( codePoint ) + " = " + Character.toString( codePoint ) );
}
} else {
System.out.println( "ERROR - Invalid code point number: " + codePoint );
}
}
System.out.println( "INFO - Demo ending. " );
}
}
运行时:
INFO - Demo starting.
32 code point is named: SPACE =
33 code point is named: EXCLAMATION MARK = !
34 code point is named: QUOTATION MARK = "
35 code point is named: NUMBER SIGN = #
36 code point is named: DOLLAR SIGN = $
37 code point is named: PERCENT SIGN = %
38 code point is named: AMPERSAND = &
…
122 code point is named: LATIN SMALL LETTER Z = z
123 code point is named: LEFT CURLY BRACKET = {
124 code point is named: VERTICAL LINE = |
125 code point is named: RIGHT CURLY BRACKET = }
126 code point is named: TILDE = ~
160 code point is named: NO-BREAK SPACE =
161 code point is named: INVERTED EXCLAMATION MARK = ¡
…
917998 code point is named: VARIATION SELECTOR-255 = ?
917999 code point is named: VARIATION SELECTOR-256 = ?
INFO - Demo ending.