Java 中文官方教程 2022 版(三十)(1)

简介: Java 中文官方教程 2022 版(三十)

教程:处理文本

原文:docs.oracle.com/javase/tutorial/i18n/text/index.html

几乎所有带有用户界面的程序都会操作文本。在国际市场上,您的程序显示的文本必须符合世界各地语言的规则。Java 编程语言提供了许多类来帮助您以与区域设置无关的方式处理文本。

检查字符属性

本节解释了如何使用Character比较方法来检查所有主要语言的字符属性。

比较字符串

在本节中,您将学习如何使用Collator类执行与区域设置无关的字符串比较。

检测文本边界

本节展示了BreakIterator类如何检测字符、单词、句子和行边界。

转换非 Unicode 文本

世界各地的不同计算机系统使用各种编码方案存储文本。本节描述了帮助您在 Unicode 和其他编码之间转换文本的类。

规范化器的 API

本节解释了如何使用规范化器的 API 来应用不同的规范化形式转换文本。

使用 JTextComponent 类处理双向文本

本节讨论了如何处理双向文本,即包含从左到右和从右到左两个方向的文本。

检查字符属性

原文:docs.oracle.com/javase/tutorial/i18n/text/charintro.html

您可以根据字符的属性对字符进行分类。例如,X 是大写字母,4 是十进制数字。检查字符属性是验证最终用户输入的数据的常见方法。例如,如果您在网上销售书籍,订单输入屏幕应验证数量字段中的字符是否都是数字。

不习惯编写全球软件的开发人员可能会通过将其与字符常量进行比较来确定字符的属性。例如,他们可能会编写如下代码:

char ch;
//...
// This code is WRONG!
// check if ch is a letter
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
    // ...
// check if ch is a digit
if (ch >= '0' && ch <= '9')
    // ...
// check if ch is a whitespace
if ((ch == ' ') || (ch =='\n') || (ch == '\t'))
    // ...

前面的代码是错误的,因为它只适用于英语和少数其他语言。要使前面的示例国际化,将其替换为以下语句:

char ch;
// ...
// This code is OK!
if (Character.isLetter(ch))
    // ...
if (Character.isDigit(ch))
    // ...
if (Character.isSpaceChar(ch))
    // ...

Character方法依赖于 Unicode 标准来确定字符的属性。Unicode 是一种支持世界主要语言的 16 位字符编码。在 Java 编程语言中,char值表示 Unicode 字符。如果您使用适当的Character方法检查char的属性,则您的代码将适用于所有主要语言。例如,如果字符是中文、德文、阿拉伯文或其他语言中的字母,则Character.isLetter方法返回true

以下列表列出了一些最有用的Character比较方法。Character API 文档完全指定了这些方法。

  • isDigit
  • isLetter
  • isLetterOrDigit
  • isLowerCase
  • isUpperCase
  • isSpaceChar
  • isDefined

Character.getType方法返回字符的 Unicode 类别。每个类别对应于Character类中定义的常量。例如,对于字符 A,getType返回Character.UPPERCASE_LETTER常量。有关getType返回的类别常量的完整列表,请参阅Character API 文档。以下示例显示了如何使用getTypeCharacter类别常量。这些if语句中的所有表达式都为true

if (Character.getType('a') == Character.LOWERCASE_LETTER)
    // ...
if (Character.getType('R') == Character.UPPERCASE_LETTER)
    // ...
if (Character.getType('>') == Character.MATH_SYMBOL)
    // ...
if (Character.getType('_') == Character.CONNECTOR_PUNCTUATION)
    // ...

比较字符串

原文:docs.oracle.com/javase/tutorial/i18n/text/collationintro.html

应用程序对文本进行排序时会执行频繁的字符串比较。例如,报告生成器在对字符串列表按字母顺序排序时执行字符串比较。

如果您的应用程序受众仅限于讲英语的人,您可能可以使用String.compareTo方法执行字符串比较。String.compareTo方法对两个字符串中的 Unicode 字符执行二进制比较。然而,对于大多数语言,这种二进制比较不能被依赖来排序字符串,因为 Unicode 值不对应字符的相对顺序。

幸运的是,Collator类允许您的应用程序为不同语言执行字符串比较。在本节中,您将学习如何在排序文本时使用Collator类。

执行与语言环境无关的比较

排序规则定义字符串的排序顺序。这些规则因语言环境而异,因为各种自然语言对单词的排序方式不同。使用Collator类提供的预定义排序规则,您可以以与语言环境无关的方式对字符串进行排序。

自定义排序规则

在某些情况下,Collator类提供的预定义排序规则可能不适用于您。例如,您可能希望对不受Collator支持的语言的字符串进行排序。在这种情况下,您可以定义自己的排序规则,并将其分配给RuleBasedCollator对象。

提高排序性能

使用CollationKey类,您可以提高字符串比较的效率。该类将String对象转换为遵循给定Collator规则的排序键。

执行与 Locale 无关的比较

原文:docs.oracle.com/javase/tutorial/i18n/text/locale.html

排序规则定义字符串的排序顺序。这些规则因区域而异,因为各种自然语言对单词的排序方式不同。您可以使用Collator类提供的预定义排序规则以与区域设置无关的方式对字符串进行排序。

要实例化Collator类,请调用getInstance方法。通常,您为默认的Locale创建一个Collator,如下例所示:

Collator myDefaultCollator = Collator.getInstance();

创建Collator时,您还可以指定特定的Locale,如下所示:

Collator myFrenchCollator = Collator.getInstance(Locale.FRENCH);

getInstance方法返回一个RuleBasedCollator,它是Collator的具体子类。RuleBasedCollator包含一组规则,这些规则确定您指定的区域设置的字符串排序顺序。这些规则对于每个区域设置都是预定义的。由于规则封装在RuleBasedCollator中,您的程序不需要特殊的例程来处理排序规则随语言变化的方式。

您调用Collator.compare方法执行与 Locale 无关的字符串比较。当第一个字符串参数小于、等于或大于第二个字符串参数时,compare方法返回小于零、等于零或大于零的整数。以下表格包含一些对Collator.compare的示例调用:

示例 返回值 解释
myCollator.compare("abc", "def") -1 "abc"小于"def"
myCollator.compare("rtf", "rtf") 0 两个字符串相等
myCollator.compare("xyz", "abc") 1 “xyz"大于"abc”

在执行排序操作时,您使用compare方法。名为CollatorDemo的示例程序使用compare方法对英语和法语单词数组进行排序。该程序展示了使用两个不同的排序器对相同单词列表进行排序时可能发生的情况:

Collator fr_FRCollator = Collator.getInstance(new Locale("fr","FR"));
Collator en_USCollator = Collator.getInstance(new Locale("en","US"));

排序方法称为sortStrings,可以与任何Collator一起使用。请注意,sortStrings方法调用compare方法:

public static void sortStrings(Collator collator, String[] words) {
    String tmp;
    for (int i = 0; i < words.length; i++) {
        for (int j = i + 1; j < words.length; j++) { 
            if (collator.compare(words[i], words[j]) > 0) {
                tmp = words[i];
                words[i] = words[j];
                words[j] = tmp;
            }
        }
    }
}

英语Collator按以下方式对单词进行排序:

peach
péché
pêche
sin

根据法语语言的排序规则,前述列表的顺序是错误的。在法语中,"péché"应该在排序列表中跟在"pêche"之后。法语Collator正确地对单词数组进行排序,如下所示:

peach
pêche
péché
sin

定制整理规则

原文:docs.oracle.com/javase/tutorial/i18n/text/rule.html

前一节讨论了如何使用区域设置的预定义规则来比较字符串。这些整理规则确定字符串的排序顺序。如果预定义的整理规则不符合您的需求,您可以设计自己的规则并将其分配给RuleBasedCollator对象。

定制的整理规则包含在传递给RuleBasedCollator构造函数的String对象中。这里是一个简单的例子:

String simpleRule = "< a < b < c < d";
RuleBasedCollator simpleCollator =  new RuleBasedCollator(simpleRule);

对于前面示例中的simpleCollator对象,a小于bb小于c,依此类推。当比较字符串时,simpleCollator.compare方法引用这些规则。用于构造整理规则的完整语法比这个简单示例更灵活和复杂。有关语法的完整描述,请参考RuleBasedCollator类的 API 文档。

接下来的示例使用两个整理器对一组西班牙语单词进行排序。此示例的完整源代码在RulesDemo.java中。

RulesDemo程序首先定义了英语和西班牙语的整理规则。该程序将按传统方式对西班牙语单词进行排序。按照传统规则排序时,字母 ch 和 ll 及其大写形式各自在排序顺序中有自己的位置。这些字符对比较就好像它们是一个字符一样。例如,ch 按照一个字母排序,在排序顺序中紧随 cz。请注意两个整理器的规则如何不同:

String englishRules = (
    "< a,A < b,B < c,C < d,D < e,E < f,F " +
    "< g,G < h,H < i,I < j,J < k,K < l,L " +
    "< m,M < n,N < o,O < p,P < q,Q < r,R " +
    "< s,S < t,T < u,U < v,V < w,W < x,X " +
    "< y,Y < z,Z");
String smallnTilde = new String("\u00F1");    // ñ
String capitalNTilde = new String("\u00D1");  // Ñ
String traditionalSpanishRules = (
    "< a,A < b,B < c,C " +
    "< ch, cH, Ch, CH " +
    "< d,D < e,E < f,F " +
    "< g,G < h,H < i,I < j,J < k,K < l,L " +
    "< ll, lL, Ll, LL " +
    "< m,M < n,N " +
    "< " + smallnTilde + "," + capitalNTilde + " " +
    "< o,O < p,P < q,Q < r,R " +
    "< s,S < t,T < u,U < v,V < w,W < x,X " +
    "< y,Y < z,Z");

以下代码行创建整理器并调用排序例程:

try {
    RuleBasedCollator enCollator = new RuleBasedCollator(englishRules);
    RuleBasedCollator spCollator =
        new RuleBasedCollator(traditionalSpanishRules);
    sortStrings(enCollator, words);
    printStrings(words);
    System.out.println();
    sortStrings(spCollator, words);
    printStrings(words);
} catch (ParseException pe) {
    System.out.println("Parse exception for rules");
}

名为sortStrings的排序例程是通用的。它将根据任何Collator对象的规则对任何单词数组进行排序:

public static void sortStrings(Collator collator, String[] words) {
    String tmp;
    for (int i = 0; i < words.length; i++) {
        for (int j = i + 1; j < words.length; j++) {
            if (collator.compare(words[i], words[j]) > 0) {
                tmp = words[i];
                words[i] = words[j];
                words[j] = tmp;
            }
        }
    }
}

使用英语整理规则排序时,单词数组如下:

chalina
curioso
llama
luz

将前面的列表与以下按照传统西班牙整理规则排序的列表进行比较:

curioso
chalina
luz
llama

提高排序性能

原文:docs.oracle.com/javase/tutorial/i18n/text/perform.html

对长字符串列表进行排序通常是耗时的。如果您的排序算法重复比较字符串,可以通过使用CollationKey类加快该过程。

一个CollationKey对象代表给定StringCollator的排序键。比较两个CollationKey对象涉及对排序键进行按位比较,比使用Collator.compare方法比较String对象更快。然而,生成CollationKey对象需要时间。因此,如果一个String只需比较一次,Collator.compare提供更好的性能。

接下来的示例使用CollationKey对象对单词数组进行排序。此示例的源代码在KeysDemo.java中。

KeysDemo程序在main方法中创建一个CollationKey对象数组。要创建CollationKey,需要在Collator对象上调用getCollationKey方法。除非两个CollationKey对象来自同一个Collator,否则无法比较它们。main方法如下:

static public void main(String[] args) {
    Collator enUSCollator = Collator.getInstance(new Locale("en","US"));
    String [] words = {
        "peach",
        "apricot",
        "grape",
        "lemon"
    };
    CollationKey[] keys = new CollationKey[words.length];
    for (int k = 0; k < keys.length; k ++) {
        keys[k] = enUSCollator. getCollationKey(words[k]);
    }
    sortArray(keys);
    printArray(keys);
}

sortArray方法调用CollationKey.compareTo方法。compareTo方法返回一个整数,如果keys[i]对象小于、等于或大于keys[j]对象,则返回小于零、等于零或大于零。请注意,程序比较的是CollationKey对象,而不是原始单词数组中的String对象。以下是sortArray方法的代码:

public static void sortArray(CollationKey[] keys) {
    CollationKey tmp;
    for (int i = 0; i < keys.length; i++) {
        for (int j = i + 1; j < keys.length; j++) {
            if (keys[i].compareTo(keys[j]) > 0) {
                tmp = keys[i];
                keys[i] = keys[j];
                keys[j] = tmp; 
            }
        }
    }
}

KeysDemo程序对CollationKey对象数组进行排序,但最初的目标是对String对象数组进行排序。为了检索每个CollationKeyString表示形式,程序在displayWords方法中调用getSourceString,如下所示:

static void displayWords(CollationKey[] keys) {
    for (int i = 0; i < keys.length; i++) {
        System.out.println(keys[i].getSourceString());
    }
}

displayWords方法打印以下行:

apricot
grape
lemon
peach

Unicode

原文:docs.oracle.com/javase/tutorial/i18n/text/unicode.html

Unicode 是一个计算行业标准,旨在一致且独特地编码世界各地书面语言中使用的字符。Unicode 标准使用十六进制表示字符。例如,值 0x0041 表示拉丁字符 A。Unicode 标准最初设计时使用 16 位来编码字符,因为主要的计算机是 16 位的个人电脑。

在创建 Java 语言规范时,接受了 Unicode 标准,并将 char 原始数据类型定义为 16 位数据类型,字符的十六进制范围为 0x0000 到 0xFFFF。

由于 16 位编码支持 2¹⁶(65,536)个字符,这不足以定义世界各地使用的所有字符,因此将 Unicode 标准扩展到 0x10FFFF,支持超过一百万个字符。在 Java 编程语言中,字符的定义无法从 16 位更改为 32 位,否则会导致数百万个 Java 应用程序无法正常运行。为了纠正这一定义,开发了一种方案来处理无法用 16 位编码的字符。

值在 16 位范围之外,且在 0x10000 到 0x10FFFF 范围内的字符被称为补充字符,并被定义为一对 char 值。

本课程包括以下部分:

  • 术语 – 解释了代码点和其他术语。
  • 补充字符作为代理 – 使用 16 位代理实现无法作为单个原始 char 数据类型实现的补充字符。
  • 字符和字符串 API – 列出了与 CharacterString 和相关类相关的 API。
  • 示例用法 – 提供了几个有用的代码片段。
  • 设计考虑 – 要牢记的设计考虑,以确保您的应用程序能够与任何语言脚本一起工作。
  • 更多信息 – 提供了更多资源列表。

术语

原文:docs.oracle.com/javase/tutorial/i18n/text/terminology.html

字符是具有语义值的最小文本单位。

字符集是一组可能被多种语言使用的字符集合。例如,拉丁字符集被英语和大多数欧洲语言使用,而希腊字符集仅被希腊语使用。

编码字符集是一个字符集,其中每个字符被分配一个唯一的数字。

代码点是可以在编码字符集中使用的值。代码点是一个 32 位的int数据类型,其中低 21 位表示有效的代码点值,而高 11 位为 0。

Unicode 的代码单元是一个 16 位的char值。例如,想象一个包含字母"abc"后跟 Deseret 长 I 的String,它用两个char值表示。该字符串包含四个字符,四个代码点,但五个代码单元。

要在 Unicode 中表示一个字符,十六进制值前缀为字符串 U+。Unicode 标准的有效代码点范围是 U+0000 到 U+10FFFF,包括两端。拉丁字符 A 的代码点值为 U+0041。代表欧元货币的字符€,其代码点值为 U+20AC。Deseret 字母表中的第一个字母,长 I,其代码点值为 U+10400。

以下表格显示了几个字符的代码点值:

如前所述,范围在 U+10000 到 U+10FFFF 之间的字符称为补充字符。从 U+0000 到 U+FFFF 的字符集有时被称为基本多语言平面(BMP)

更多术语可以在更多信息页面上列出的Unicode 术语词汇表中找到。

补充字符作为代理

原文:docs.oracle.com/javase/tutorial/i18n/text/supplementaryChars.html

为了支持补充字符而不改变char原始数据类型并导致与之前的 Java 程序不兼容,补充字符被定义为一对称为代理的代码点值。 第一个代码点来自U+D800U+DBFF高代理范围,第二个代码点来自U+DC00U+DFFF低代理范围。 例如,Deseret 字符 LONG I,U+10400,是用这对代理值定义的:U+D801U+DC00

字符和字符串 API

原文:docs.oracle.com/javase/tutorial/i18n/text/characterClass.html

Character 类封装了 char 数据类型。对于 J2SE 发布的第 5 版,许多方法被添加到 Character 类中以支持补充字符。这个 API 分为两类:将 char 和代码点值之间进行转换的方法以及验证或映射代码点的方法。

本节描述了 Character 类中可用方法的一个子集。有关可用 API 的完整列表,请参阅 Character 类规范。

转换方法和 Character 类

以下表格包括了 Character 类中最有用的转换方法或便于转换的方法。codePointAtcodePointBefore 方法包含在此列表中,因为文本通常以序列的形式出现,比如一个 String,这些方法可以用来提取所需的子字符串。

方法 描述
toChars(int codePoint, char[] dst, int dstIndex) toChars(int codePoint) 将指定的 Unicode 代码点转换为其 UTF-16 表示,并将其放入一个 char 数组中。示例用法:Character.toChars(0x10400)
toCodePoint(char high, char low) 将指定的代理对转换为其补充代码点值。

| codePointAt(char[] a, int index) codePointAt(char[] a, int index, int limit)

codePointAt(CharSequence seq, int index) | 返回指定索引处的 Unicode 代码点。第三个方法接受一个 CharSequence,第二个方法对索引施加了上限。 |

| codePointBefore(char[] a, int index) codePointBefore(char[] a, int index, int start)

codePointBefore(CharSequence seq, int index)

codePointBefore(char[], int, int) | 返回指定索引之前的 Unicode 代码点。第三个方法接受CharSequence,其他方法接受char数组。第二个方法对索引强制执行下限。 |

charCount(int codePoint) 对于可以由单个char表示的字符,返回值为 1。对于需要两个char表示的补充字符,返回值为 2。

字符类中的验证和映射方法

以前使用char原始数据类型的一些方法,如isLowerCase(char)isDigit(char),已被支持补充字符的方法所取代,如isLowerCase(int)isDigit(int)。以前的方法得到支持,但不适用于补充字符。为了创建一个全球应用程序并确保您的代码与任何语言无缝配合,建议您使用这些方法的新形式。

请注意,出于性能原因,大多数接受代码点的方法不会验证代码点参数的有效性。您可以使用isValidCodePoint方法进行验证。

以下表格列出了Character类中的一些验证和映射方法。

方法 描述
isValidCodePoint(int codePoint) 如果代码点在 0x0000 到 0x10FFFF(包括)范围内,则返回 true。
isSupplementaryCodePoint(int codePoint) 如果代码点在 0x10000 到 0x10FFFF(包括)范围内,则返回 true。
isHighSurrogate(char) 如果指定的char在\uD800 到\uDBFF(包括)的高代理范围内,则返回 true。
isLowSurrogate(char) 如果指定的char在\uDC00 到\uDFFF(包括)的低代理范围内,则返回 true。
isSurrogatePair(char high, char low) 如果指定的高代理和低代理代码值表示有效的代理对,则返回 true。
codePointCount(CharSequence, int, int) codePointCount(char[], int, int) 返回CharSequencechar数组中的 Unicode 代码点数。
isLowerCase(int) isUpperCase(int) 如果指定的 Unicode 代码点是小写或大写字符,则返回 true。
isDefined(int) 如果指定的 Unicode 代码点在 Unicode 标准中定义,则返回 true。
isJavaIdentifierStart(char) isJavaIdentifierStart(int) 如果指定的字符或 Unicode 代码点可作为 Java 标识符中的第一个字符,则返回 true。

| isLetter(int) isDigit(int)

isLetterOrDigit(int) | 如果指定的 Unicode 代码点是字母、数字或字母数字,则返回 true。 |

getDirectionality(int) 返回给定 Unicode 代码点的 Unicode 方向性属性。
Character.UnicodeBlock.of(int codePoint) 返回表示包含给定 Unicode 代码点的 Unicode 块的对象,如果代码点不是已定义块的成员,则返回null

字符串类中的方法

StringStringBufferStringBuilder 类也有构造函数和方法,可以处理补充字符。以下表格列出了一些常用方法。要查看可用 API 的完整列表,请参阅 StringStringBufferStringBuilder 类的 javadoc。

构造函数或方法 描述
String(int[] codePoints, int offset, int count) 分配一个新的 String 实例,其中包含来自 Unicode 代码点数组的子数组的字符。

| String.codePointAt(int index) StringBuffer.codePointAt(int index)

StringBuilder.codePointAt(int index) | 返回指定索引处的 Unicode 代码点。 |

| String.codePointBefore(int index) StringBuffer.codePointBefore(int index)

StringBuilder.codePointBefore(int index) | 返回指定索引之前的 Unicode 代码点。 |

| String.codePointCount(int beginIndex, int endIndex) StringBuffer.codePointCount(int beginIndex, int endIndex)

StringBuilder.codePointCount(int beginIndex, int endIndex) | 返回指定范围内的 Unicode 代码点数。 |

| String.offsetByCodePoints(int index, int codePointOffset) StringBuffer.offsetByCodePoints(int index, int codePointOffset)

StringBuilder.offsetByCodePoints(int index, int codePointOffset) | 返回给定索引偏移给定代码点数量后的索引。 |

Java 中文官方教程 2022 版(三十)(2)https://developer.aliyun.com/article/1487960

相关文章
|
2月前
|
Java 开发工具 Android开发
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
|
3天前
|
移动开发 前端开发 Java
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
JavaFX是Java的下一代图形用户界面工具包。JavaFX是一组图形和媒体API,我们可以用它们来创建和部署富客户端应用程序。 JavaFX允许开发人员快速构建丰富的跨平台应用程序,允许开发人员在单个编程接口中组合图形,动画和UI控件。本文详细介绍了JavaFx的常见用法,相信读完本教程你一定有所收获!
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
|
17天前
|
NoSQL Java 关系型数据库
Liunx部署java项目Tomcat、Redis、Mysql教程
本文详细介绍了如何在 Linux 服务器上安装和配置 Tomcat、MySQL 和 Redis,并部署 Java 项目。通过这些步骤,您可以搭建一个高效稳定的 Java 应用运行环境。希望本文能为您在实际操作中提供有价值的参考。
95 26
|
24天前
|
安全 Java 编译器
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
|
24天前
|
Java 开发工具 Android开发
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
|
1月前
|
Java 编译器 Android开发
Kotlin教程笔记(28) -Kotlin 与 Java 混编
Kotlin教程笔记(28) -Kotlin 与 Java 混编
33 2
|
23天前
|
Java 数据库连接 编译器
Kotlin教程笔记(29) -Kotlin 兼容 Java 遇到的最大的“坑”
Kotlin教程笔记(29) -Kotlin 兼容 Java 遇到的最大的“坑”
42 0
|
1月前
|
安全 Java 编译器
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
|
1月前
|
Java 开发工具 Android开发
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
|
1月前
|
Java 编译器 Android开发
Kotlin教程笔记(28) -Kotlin 与 Java 混编
Kotlin教程笔记(28) -Kotlin 与 Java 混编