2

就在前几天,我遇到了一个奇怪的奇怪错误。我有一串必须构建的字符。作为分隔符,我与之通信的主机系统使用了 char 254。无论如何,我构建了我的字符串并将其发送到主机。在主机上,我收到 char 222 作为分隔符!在挠了挠头并深入研究之后,这似乎很奇怪

十六进制:FE,二进制:11111110

变成了

十六进制:DE,二进制:11011110

我尝试了 Locale.getDefault() 和 Locale.ENGLISH 无济于事。

难道 String.toUpperCase 的实现对所有字符都有一个掩码,除了特定的硬编码字符?

现在我正在使用以下方法来解决这个问题:

public static String toUpperCase(String input) {

    char[] chars = input.toCharArray();


    for(int i = 0; i < chars.length; ++i ) {

        if( chars[i] > 96 && chars[i] < 123 ) {

            chars[i] &= 223;
        }

    }

    return new String(chars);

}

我的问题是我错过了什么吗?有没有更好的方法我不知道?非常感谢!

4

5 回答 5

7

Unicode 字符 254 是小写的 thorn,þ在冰岛语中使用的一个字母大致代表“th”的声音。它的大写版本是字符 222,大写 thorn Þ。你期望会发生什么?

于 2013-09-17T21:39:05.087 回答
3

Java 使用UTF-16一般。Java 中原始类型的前 256 个值char与 Latin-1 字符集完全相同,此处给出。在该图表上,您可以看到大写值 254(下冰岛刺)会将其转换为值 222(上冰岛刺)。

道德是:不要在字符串中使用大小写作为分隔符的值。

于 2013-09-17T21:38:09.397 回答
2

根据http://www.unicode.org/faq/casemap_charprop.html

Unicode 标准为每个单独的字符定义了默认大小写映射,每个字符被单独考虑。此映射不提供字符出现的上下文,也不提供在自然语言文本中工作时必须应用的语言特定规则。

upper/lowerCase因此,无论您使用什么语言环境,这些方法的工作方式看起来几乎相同。指定不同的区域设置可能会影响一些特定的字母(如土耳其语中的“i”),但它不会upper/lowerCase停止处理整个字母组。因此,指定 Locale.ENGLISH 不会upperCase忽略冰岛字母或俄语或希腊字母。

于 2013-09-17T22:10:27.467 回答
1

String.toUpperCase() 除了在给定的字符集中转换为大写之外,不可能做任何事情。

您的问题似乎暗示您的系统和主机之间的链接是使用 8 位字符集(ASCII?)完成的。但是,Java 在各种字符集(UTF-16、UTF-8 等)中使用 16 位字符,因此,无论是解释字符集还是转换为 8 位,都必须进行转换。如果字符集是 UTF-8,那么前 127 个字符用 ASCII 映射 1-1。但是,您关心的是超出该范围的字符,因此需要进行更复杂的转换。我猜这就是问题所在。

所以我认为你应该:

  1. 找出主机期望的字符集
  2. 找出从 Java 16 到字符的转换发生在哪里。你自己在做吗?

我猜想奇怪的行为就在那里。

抱歉,我无法提供更多帮助。如果您向我提供有关通讯链接和转换过程的更多详细信息,我也许可以更清楚地了解正在发生的事情

于 2013-09-17T21:40:06.233 回答
1
Locale trlocale= Locale.forLanguageTag("tr-TR");
Locale enLocale = Locale.forLanguageTag("en_US");
System.out.println("üğişçö".toUpperCase(new java.util.Locale("tr", "TR")));
System.out.println("üğişçö".toUpperCase(new java.util.Locale("en", "EN")));
value = new String(value.getBytes("UTF-8"), "UTF-8");
于 2016-03-11T14:59:15.723 回答