在Java中过滤用户字体中缺少的字符

时间:2012-02-09 12:26:24

标签: java unicode fonts filter non-printable

我想用Java(作为练习)构建一个有点简单的表来检查最终用户字体中是否存在合法的可打印Unicode代码点。由于某些字体无法打印有效的代码点,因此我必须知道哪些可打印的代码点仍然缺少用户的字体,因此无法打印。

例如,如果一个字体仅支持拉丁字符,我就无法使用它来打印希腊字符,更不用说日文字符了。 Unicode表示它们都是可打印的,但用户的字体可能不够好。

经过一番研究后,我已经能够在Eclipse中打印大部分字符(通过调用编码)。但是我的输出中仍然有一堆未知/不可打印的字符,因为当我查看输出时,我看到所有这些空矩形表示我的一些可打印字符。

我已经尝试过滤它们,但我找不到任何方法来做到这一点。仅供参考我基本上只是将角色的值设置为50,100或1000,然后通过for循环从那里增加它以检查我可以或不可以(或不应该?)打印的字符。

任何人都可以给我一些关于从哪里开始的提示吗?

2 个答案:

答案 0 :(得分:3)

您的任务实际上比编码要复杂一些,因为您尝试打印的字体会对输出产生很大影响。即并非所有字体都支持相同的字符集。事实上,字符范围differs wildly from font to font的支持。

那就是说,你的问题现在变成:我如何检测某个字体是否支持给定的字符? that question has been asked and answered ... See here for the Java doc of the canDisplay函数是the Font class的成员。

答案 1 :(得分:2)

目前还不清楚你在这里究竟是什么意思。如果您打算按数字进行播放,那么Annex C of Unicode Technical Standard #18 on Unicode Regular Expressions会给出具体建议,即将“可打印”代码点定义为具有print属性的任何代码点,其中该属性定义为< / p>

  • \p{print}表示[[\p{graph}\p{blank}]&&[^\p{gc=Control}]]
  • \p{graph}表示[^\p{Whitespace}\p{gc=Control}\p{gc=Surrogate}\p{gc=Unassigned}]
  • \p{blank}表示[\p{Whitespace}&&[^\N{LF}\N{VT}\N{FF}\N{CR}\N{NEL}\p{gc=Line_Separator}\{gc=Paragraph_Separator}]

或者,as the Java 1.7 Pattern class documents these,前提是您编译了启用了the new-to-Java7 Pattern.UNICODE_CHARACTER_CLASS标志的模式:

  • \p{Graph}可见字符:[^\p{IsWhite_Space}\p{gc=Cc}\p{gc=Cs}\p{gc=Cn}]
  • \p{Print}可打印字符:[\p{Graph}\p{Blank}&&[^\p{Cntrl}]]
  • \p{Blank}空格或标签:[\p{IsWhite_Space}&&[^\p{gc=Zl}\p{gc=Zp}\x0a\x0b\x0c\x0d * \x85]]
  • \p{Cntrl}控制角色:\p{gc=Cc}
  • \p{XDigit}十六进制数字:[\p{gc=Nd}\p{IsHex_Digit}]
  • \p{Space}一个空格字符:\p{IsWhite_Space}

在'可打印'字符

如果您只是使用像Java的(?U)\p{print}模式属性(或Character类中的等价物)那样合理的东西,那么您仍然需要做出一些“有趣”的决定。

考虑以下每个代码点:

U+000007 gc=Cc columns=0 print=0 graph=0  ALERT
U+000008 gc=Cc columns=0 print=0 graph=0  BACKSPACE
U+000009 gc=Cc columns=0 print=0 graph=0  CHARACTER TABULATION
U+00000C gc=Cc columns=0 print=0 graph=0  FORM FEED (FF)
U+00000D gc=Cc columns=0 print=0 graph=0  CARRIAGE RETURN (CR)
U+000020 gc=Zs columns=1 print=1 graph=0  SPACE
U+000021 gc=Po columns=1 print=1 graph=1  EXCLAMATION MARK
U+000041 gc=Lu columns=1 print=1 graph=1  LATIN CAPITAL LETTER A
U+000061 gc=Ll columns=1 print=1 graph=1  LATIN SMALL LETTER A
U+000080 gc=Cc columns=0 print=0 graph=0  PADDING CHARACTER
U+000085 gc=Cc columns=0 print=0 graph=0  NEXT LINE (NEL)
U+00008D gc=Cc columns=0 print=0 graph=0  REVERSE LINE FEED
U+0000AB gc=Pi columns=1 print=1 graph=1  LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
U+0000AD gc=Cf columns=0 print=1 graph=1  SOFT HYPHEN
U+0002B0 gc=Lm columns=1 print=1 graph=1  MODIFIER LETTER SMALL H
U+0002C6 gc=Lm columns=1 print=1 graph=1  MODIFIER LETTER CIRCUMFLEX ACCENT
U+000302 gc=Mn columns=0 print=1 graph=1  COMBINING CIRCUMFLEX ACCENT
U+00036A gc=Mn columns=0 print=1 graph=1  COMBINING LATIN SMALL LETTER H
U+001100 gc=Lo columns=2 print=1 graph=1  HANGUL CHOSEONG KIYEOK
U+002028 gc=Zl columns=0 print=0 graph=0  LINE SEPARATOR
U+002029 gc=Zp columns=0 print=0 graph=0  PARAGRAPH SEPARATOR
U+00202B gc=Cf columns=0 print=1 graph=1  RIGHT-TO-LEFT EMBEDDING
U+00202F gc=Zs columns=1 print=1 graph=0  NARROW NO-BREAK SPACE
U+002060 gc=Cf columns=0 print=1 graph=1  WORD JOINER
U+002061 gc=Cf columns=0 print=1 graph=1  FUNCTION APPLICATION
U+002062 gc=Cf columns=0 print=1 graph=1  INVISIBLE TIMES
U+002064 gc=Cf columns=0 print=1 graph=1  INVISIBLE PLUS
U+002EC1 gc=So columns=2 print=1 graph=1  CJK RADICAL TIGER
U+002F0B gc=So columns=2 print=1 graph=1  KANGXI RADICAL EIGHT
U+003000 gc=Zs columns=2 print=1 graph=0  IDEOGRAPHIC SPACE
U+003008 gc=Ps columns=2 print=1 graph=1  LEFT ANGLE BRACKET
U+00300A gc=Ps columns=2 print=1 graph=1  LEFT DOUBLE ANGLE BRACKET
U+00300C gc=Ps columns=2 print=1 graph=1  LEFT CORNER BRACKET
U+00302B gc=Mn columns=0 print=1 graph=1  IDEOGRAPHIC RISING TONE MARK
U+003030 gc=Pd columns=2 print=1 graph=1  WAVY DASH
U+003037 gc=So columns=2 print=1 graph=1  IDEOGRAPHIC TELEGRAPH LINE FEED SEPARATOR SYMBOL
U+003041 gc=Lo columns=2 print=1 graph=1  HIRAGANA LETTER SMALL A
U+00E000 gc=Co columns=1 print=1 graph=1 <unnamed codepoint in blk=Private_Use_Area>
U+00F8FF gc=Co columns=1 print=1 graph=1 <unnamed codepoint in blk=Private_Use_Area>
U+00FB1E gc=Mn columns=0 print=1 graph=1  HEBREW POINT JUDEO-SPANISH VARIKA
U+00FE00 gc=Mn columns=0 print=1 graph=1  VARIATION SELECTOR-1
U+00FE23 gc=Mn columns=0 print=1 graph=1  COMBINING DOUBLE TILDE RIGHT HALF
U+00FE58 gc=Pd columns=2 print=1 graph=1  SMALL EM DASH
U+00FE77 gc=Lo columns=1 print=1 graph=1  ARABIC FATHA MEDIAL FORM
U+00FEFF gc=Cf columns=0 print=1 graph=1  ZERO WIDTH NO-BREAK SPACE
U+00FF06 gc=Po columns=2 print=1 graph=1  FULLWIDTH AMPERSAND
U+00FFFA gc=Cf columns=0 print=1 graph=1  INTERLINEAR ANNOTATION SEPARATOR
U+00FFFD gc=So columns=1 print=1 graph=1  REPLACEMENT CHARACTER
U+01B000 gc=Lo columns=2 print=1 graph=1  KATAKANA LETTER ARCHAIC E
U+01D165 gc=Mc columns=1 print=1 graph=1  MUSICAL SYMBOL COMBINING STEM
U+01D167 gc=Mn columns=0 print=1 graph=1  MUSICAL SYMBOL COMBINING TREMOLO-1
U+100002 gc=Co columns=1 print=1 graph=1 <unnamed codepoint in blk=Supplementary_Private_Use_Area-B>

他们中的一些人对于什么,甚至是否是他们的印刷是非常有条件的。例如,U + F8FF的<>对你来说是什么样的?

然后你必须决定如何处理标签和退格。

另外,您必须考虑用于构建Unicode 扩展字形集群的各种\p{Grapheme_Extend}代码点;也就是说,用户可见的字符。并非所有这些都是非间距标记。事实上,有些不是标记,而是字母!有些根本不是可打印字符,但它们会更改不可避免地附加的可打印\p{Grapheme_Base}字符;仅考虑变异选择器的一个例子。

警告

这给我们带来了一个至关重要的观点,这个观点经常被那些想成为Java的程序员所遗忘,即使没有完全被遗忘,也常常被低估。

始终,始终记住, Java字符不是Unicode字符! Unicode字符有两个合理的定义,而Java则不提供。以下是两个合理的定义:

  • 如果字符是程序员可见意义上的字符,则字符是Unicode代码点。这是.在正则表达式引擎中匹配的内容,例如,无论您使用的是Sun还是ICU。
  • 如果字符是用户可见意义上的字符,则字符是Unicode扩展字形集群。这是({ICU not Sun)正则表达式引擎中\X匹配的内容。

Java所谓的“字符”是实际Unicode代码点的可变宽度UTF-16表示的低级别,抽象的2字节元素。它既不是抽象的代码点,也不是抽象的字形。它不是一个抽象的任何东西。 Java char违反了抽象的范围。

是的,有些Java类为您提供了codePointAt接口,您应该绝对使用那些可用的接口。但是在很多方面,这里需要花费很长时间来解释, Java从根本上打破了它的角色抽象 - 因为它没有。

这使得在Java中使用Unicode字符和字符串时最容易出错,并且通常几乎不可能。

祝你好运。