2013-09-17 1 views
2

На днях я столкнулся с странной странной ошибкой. У меня была строка символов, которые мне пришлось строить. И в качестве разделителя хост-системы я общался с используемым char 254. В любом случае я строю свою строку и отправил ее на хост. На хосте я принимал char 222 в качестве разделителя! После того, как чесать голову и глядя в него глубже, казалось странным, чтоJava String.toUpperCase()

шестигранной: FE, двоичная: 11111110

превращался в

шестнадцатеричном: DE, двоичная: 11011110

Я попытался локали .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); 

} 

мой вопрос я что-то отсутствует? Есть ли лучший способ, о котором я не знаю? Огромное спасибо!

ответ

3

Java использует UTF-16 в целом. Первые 256 значений примитивного типа в Java точно такие же, как набор символов Latin-1, который присваивается here. На этой диаграмме вы можете увидеть, что значение капитализации 254 (нижний исландский шип) преобразует его в значение 222 (верхний исландский шип).

Мораль: не используйте значения, которые имеют случай как разделители в строке.

+0

Спасибо! Так что, другими словами, я идиот, а не разработчик по умолчанию toUpperCase(). Это имеет смысл теперь, когда я действительно знаю об исландском звуке примерно для «th», как сказал Йони выше. Я не реализовал хост-систему, поэтому я не мог контролировать, что они использовали в качестве разделителей. На самом деле это очень старая система на основе PICK. Я отмечаю это как ответ за полезную ссылку. –

7

Юникодский символ 254 - это нижний регистр, þ, письмо, используемое на исландском языке, которое стоит примерно для «th» звука. Его версия в верхнем регистре - символ 222, верхний регистр тонов Þ. Чего вы ожидали?

1

Это не может быть так, что String.toUpperCase() делает что-либо, кроме преобразования в верхний регистр в заданном наборе символов.

Возможно, ваш вопрос подразумевает, что связь между вашей системой и хостом выполняется с использованием 8-битного набора символов (ASCII?). Однако Java использует 16-битные символы в различных наборах символов (UTF-16, UTF-8 и т. Д.). Таким образом, должно быть что-то, что делает преобразование, как при интерпретации набора символов, так и при преобразовании в 8 бит. Если набор символов UTF-8, то первые 127 символов отображают 1-1 с ASCII. Однако вы обеспокоены символами вне этого диапазона, поэтому требуется более сложное преобразование. Я предполагаю, что это проблема.

Так что я думаю, вы должны:

  1. Узнайте, что использовал строки установить хост ожидает
  2. Узнайте, где преобразование из Java-16, но гольцов происходит. Вы сами это делаете?

Я бы предположил, что странное поведение где-то там.

Извините, я не могу больше помочь.Если вы дадите мне более подробную информацию о ссылке комм, и процесс преобразования, я мог бы пролить свет на то, что происходит на

2

По http://www.unicode.org/faq/casemap_charprop.html:

Стандарт Unicode определяет отображение случай по умолчанию для каждого индивидуального символа, причем каждый символ рассматривается отдельно. Это сопоставление не предусматривает контекста, в котором отображается символ , а также для правил, специфичных для языка, которые должны применяться, когда работает на языке естественного языка.

Таким образом, методы upper/lowerCase работают практически одинаково независимо от того, какой язык вы использовали. Указание другого языка может повлиять на несколько конкретных букв (например, «i» на турецком языке), но не делает upper/lowerCase прекращением работы над целыми группами букв. Поэтому указание Locale.ENGLISH не делает upperCase игнорировать исландские буквы - или русские или греческие буквы.

0
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");