使用 Java 中的 toUpperCase() 将 ß.cfg 转换为大写。

7
我正在尝试以下代码:

String s1 = "ß.cfg";
System.out.println (s.toUpperCase());

我得到的输出是SS.CFG,因为Unicode没有定义ß的大写版本,而我想要的输出是ß.CFG

有没有办法实现这个需求?


1
自2008年以来,有一个大写版本:(U+1E9E),但标准的 toUpperCase 算法在2018年仍将 ß 映射为 SS - Andrey Tyukin
7个回答

6
"

ß"字符等同于“ss”(例如在德语中使用),并且这在您的区域设置中定义(您在应用程序中使用的区域设置)。

您可以尝试使用以下方法尝试不同的Locale进行一些实验:

"
toUpperCase(Locale locale) 

编辑:如用户所说,此方法无效,一个可能的解决办法(不太优雅)是:

    String s1 = new String ("auß.cfg").replace('ß', '\u9999');
    System.out.println (s1.toUpperCase(Locale.UK).replace('\u9999', 'ß'));

即使传递不同的区域设置,输出结果仍然完全相同,没有任何变化。 - Umesh Awasthi
你是对的,Unicode中的前255个字符使用Latin1进行翻译(Character类): if (codePoint <= FAST_PATH_MAX) { // FAST_PATH_MAX = 255 upperCase = CharacterDataLatin1.toUpperCaseEx(codePoint); } else {... - greuze
我会直接使用 'ẞ',而不是 '\u9999',并且最后的替换也不需要。 - user16320675

5

toUpperCase( Locale )的文档明确说明会发生以下情况:

由于大小写映射并不总是1:1字符映射,因此生成的字符串可能与原始字符串长度不同。

小写字母sharp s -> 两个字母:SS


我有没有办法实现我想做的事情? - Umesh Awasthi
我认为你需要编写自己的 toUppercase 实现,以便它能正确处理这个字母。也许可以扫描 ß 并替换它,然后再委托给现有的方法...... Java 实现是获取大写 ß 的正确方式。 - tim_yates
不,这不再是正确的方法了。或者这取决于你对“正确”的定义。在过去,德语中没有ẞ这个字母,因此将ß转换为SS是正确的,但现在,德语语言有一个大写的ß,即ẞ。我明白Java实现无法为了兼容而改变,但这并不是我所说的正确。 - Yava

4
Java的实现只是遵循Unicode规范。而Unicode规范如下所述:
# ================================================================================
# Unconditional mappings
# ================================================================================

# The German es-zed is special--the normal mapping is to SS.
# Note: the titlecase should never occur in practice. It is equal to titlecase(uppercase(<es-zed>))

00DF; 00DF; 0053 0073; 0053 0053; # LATIN SMALL LETTER SHARP S

参考文献:http://unicode.org/Public/UNIDATA/SpecialCasing.txt

如果您想实现一种与Unicode不同的大写转换形式,您需要自己指定和实现它。


(如果您想看到一堆人在讨论“大写ß”的事情,可以阅读这个电子邮件线程 - http://unicode.org/mail-arch/unicode-ml/y2007-m05/0007.html)


1
尝试使用{{link1:java.lang.String.toUpperCase(java.util.Locale)}}。

1

看起来Characeter.toUpperCase()忽略了这些规则,因此您可以使用它来实现所需的转换:

与Character大小写映射方法相比,String大小写映射方法具有多个优点。String大小写映射方法可以执行区域设置敏感的映射、上下文敏感的映射和1:M字符映射,而Character大小写映射方法则不能。


0
这将解决问题。
char[] chars = "ßdenrä".toCharArray();
for (int i = 0; i < chars.length; i++) {
chars[i] = Character.toUpperCase(chars[i]);
}
String output = new String(chars);
System.out.println(output);

结果:ßDENRÄ

0

如果原词中同时出现"ß"和"SS",可以使用以下简单方法:

    private String toUppercaseWithSharpS(String originString) {
    Pattern sharpSPattern = Pattern.compile("ß");
    Matcher shaprSMatcher = sharpSPattern.matcher(originString);
    String placeholder = "SHARP-S";
    String upperCasedString = shaprSMatcher.replaceAll(placeholder);
    upperCasedString = upperCasedString.toUpperCase(); //replaces ß with SS, see https://bugs.openjdk.org/browse/JDK-8186073);
    upperCasedString = upperCasedString.replaceAll(placeholder, "ß");

    return upperCasedString;
}

为什么不只是使用originString.replace("ß", "ẞ").toUpperCase()呢?(至少如果原始文本包含SHARP-S,它不会失败,并且稍微简单一些)。顺便说一下,没有必要使用正则表达式来替换纯文本。 - user16320675
或者 ... .replace('ß', 'ẞ').toUpperCase() - user16320675
当然可以,不过在我的情况下,有一个奇怪的目标是让输出中的所有字母都是大写,但是带有小写的ß。期望的结果(虽然奇怪):PARISER STRAßE您的建议会产生:PARISER STRAẞE - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接