2

ちょうど先日、奇妙な奇妙なバグに遭遇しました。構築しなければならない文字列がありました。そして、区切り文字として、ホストシステムと通信していた char 254 を使用していました。とにかく、文字列を作成してホストに送信しました。ホストでは、区切り文字として char 222 を受け取りました! 頭をかきむしり、深く調べてみると、それは奇妙に思えた

16 進数: FE、2 進数: 11111110

に変わっていた

16 進数: DE、2 進数: 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 は、þアイスランド語で使用される小文字のとげで、おおよそ「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使用したロケールに関係なく、メソッドはほぼ同じように機能するようです。upper/lowerCase別の Locale を指定すると、いくつかの特定の文字 (トルコ語の「i」など) に影響する場合がありますが、文字のグループ全体での作業が停止するわけではありません。そのため、Locale.ENGLISH を指定しても、upperCaseアイスランド文字 (またはロシア語またはギリシャ文字) は無視されません。

于 2013-09-17T22:10:27.467 に答える
1

String.toUpperCase() が特定の文字セットで大文字に変換する以外のことはできません。

あなたの質問は、システムとホスト間のリンクが 8 ビット文字セット (ASCII ?) を使用して行われていることを暗示しているようです。ただし、Java はさまざまな文字セット (UTF-16、UTF-8 など) で 16 ビット文字を使用します。そのため、文字セットの解釈と 8 ビットへの変換の両方で、変換を行う何かが必要です。文字セットが UTF-8 の場合、最初の 127 文字は 1-1 を ASCII にマップします。ただし、その範囲外の文字に関心があるため、より複雑な変換が必要です。そこが問題だと思います。

だから私はあなたがすべきだと思います:

  1. ホストが期待している文字セットを調べる
  2. Java 16-but chars からの変換がどこで行われているかを調べます。あなたは自分でそれをやっていますか?

奇妙な振る舞いはどこかにあると思います。

申し訳ありませんが、これ以上お役に立てません。通信リンクと変換プロセスの詳細を教えていただければ、何が起こっているのかをさらに明らかにできるかもしれません

于 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 に答える