Java UTF-8 странное поведение

В целом доберитесь/методы установки, ниспровергают инкапсуляцию путем представления внутренней реализации и состояния. Если Вы используете, получают/устанавливают на каждой части данных в Вашем классе, скорее всего, лучше просто сделать это простым составным типом только с общедоступными данными и никакими методами.

я действительно не покупаю, которые получают/устанавливают, помогает сделать вещи как, например, сделать Ваш класс ориентированным на многопотоковое исполнение, потому что ограниченная синхронизация, которую можно обеспечить, защищает от всех неправильных видов условий состязания.

5
задан laalto 13 August 2009 в 14:16
поделиться

4 ответа

Консоль, на которую вы выводите (например, Windows), может не поддерживать Unicode и искажать символы. Вывод на консоль не является хорошим представлением данных.

Вместо этого попробуйте записать вывод в файл, убедившись, что кодировка правильная в FileWriter, а затем откройте файл в удобном для юникода редакторе.

В качестве альтернативы, используйте отладчик, чтобы убедиться, что символы соответствуют вашим ожиданиям. Только не доверяйте консоли.

9
ответ дан 18 December 2019 в 09:08
поделиться

Код в порядке, но, как сказал скаффман, ваша консоль, вероятно, не поддерживает соответствующий символ.

Чтобы точно проверить, вам нужно распечатать значения Unicode символа:

public class Test {
    public static void main(String[] args) throws Exception {
        byte[] utf8 = { 105, -52, -120 };
        String text = new String(utf8, "UTF-8");
        for (int i=0; i < text.length(); i++) {
            System.out.println(Integer.toHexString(text.charAt(i)));
        }
    }
}

Это печатает 69, 308 - что является правильным (U + 0069, U + 0308).

4
ответ дан 18 December 2019 в 09:08
поделиться

Вы оба правы. Спасибо !!

Вот как я наконец решил проблему в Eclipse для Windows:

  • На вкладке «Конфигурация запуска», на вкладке «Аргументы» я добавил " -Dfile.encoding = UTF-8 " в Аргументы виртуальной машины
  • В конфигурации «Выполнить» на вкладке «Общие» я установил кодировку консоли на UTF-8

И изменил код следующим образом:

byte[] utf8 = { 105, -52, -120 };
System.out.print("{{");
for(int i = 0; i < utf8.length; ++i)
{
    int value = utf8[i] & 0xFF;
    System.out.print(Integer.toHexString(value));
}
System.out.println("}}");

PrintStream sysout = new PrintStream(System.out, true, "UTF-8");
sysout.print(">" + new String(utf8, "UTF-8"));

Вывод:

{{69cc88}}
> ï

Спасибо!

4
ответ дан 18 December 2019 в 09:08
поделиться

Java, не без оснований, кодирует символы Unicode в байты, закодированные в собственной системе, прежде чем записать их в stdout . Некоторые операционные системы, как и многие дистрибутивы Linux, используют UTF-8 в качестве набора символов по умолчанию, что приятно.

В Windows все немного по-другому по ряду причин обратной совместимости. Системная кодировка по умолчанию будет одной из кодовых страниц « ANSI », и если вы откроете командную строку по умолчанию (cmd.exe), она будет одной из старых кодовых страниц « OEM » DOS (хотя там можно получить ANSI и Unicode , немного поработав ).

Поскольку U + 0308 не входит ни в один из наборов символов "ANSI" (вероятно, 1252 в вашем случае), это ' ll будут закодированы как символ ошибки (обычно это вопросительный знак).

Альтернативой включению Unicode все является нормализация объединяющей последовательности U + 0069 U + 0308 до одного символа U + 00EF:

  public static void emit(String foo) throws IOException {
    System.out.println("Literal: " + foo);
    System.out.print("Hex: ");
    for (char ch : foo.toCharArray()) {
      System.out.print(Integer.toHexString(ch & 0xFFFF) + " ");
    }
    System.out.println();
  }

  public static void main(String[] args) throws IOException {
    String foo = "\u0069\u0308";
    emit(foo);
    foo = Normalizer.normalize(foo, Normalizer.Form.NFC);
    emit(foo);
  }

В windows-1252 этот код выдаст:

Literal: i?
Hex: 69 308 
Literal: ï
Hex: ef 
1
ответ дан 18 December 2019 в 09:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: