Java 8 UTF-16 не является кодировкой по умолчанию, но UTF-8 - PullRequest
1 голос
/ 10 марта 2019

Я занимался кодированием с помощью String в Java8, Java 11, но этот вопрос основан на Java 8. У меня есть небольшой фрагмент.

final char e = (char)200;//È

Я просто подумал, что символы между 0,255 [Ascii +расширенный Ascii] всегда помещался бы в байт только потому, что 2 ^ 8 = 256, но это, похоже, не соответствует действительности. Я пробовал на сайте https://mothereff.in/byte-counter и заявляет, что символ занимает 2 байта, может кто-нибудь объяснить мне.

Другой вопрос во многих постах гласит, что Java - это UTF-16, но на моем компьютере под управлением Windows 7 в этом фрагменте возвращается UTF-8.

String csn = Charset.defaultCharset().name();

Является ли эта платформа зависимой??

У меня есть другие вопросы, попробуйте этот фрагмент.

final List<Charset>charsets = Arrays.asList(StandardCharsets.ISO_8859_1,StandardCharsets.US_ASCII,StandardCharsets.UTF_16,StandardCharsets.UTF_8);
    charsets.forEach(a->print(a,"È"));
    System.out.println("getBytes");
    System.out.println(Arrays.toString("È".getBytes()));
    charsets.forEach(a->System.out.println(a+" "+Arrays.toString(sb.toString().getBytes(a))));

private void print(final Charset set,final CharSequence sb){
    byte[] array = new byte[4];              
    set.newEncoder()
            .encode(CharBuffer.wrap(sb), ByteBuffer.wrap(array), true);
    final String buildedString = new String(array,set);
    System.out.println(set+" "+Arrays.toString(array)+" "+buildedString+"<<>>"+buildedString.length());    
}

И распечатки

run:
ISO-8859-1 [-56, 0, 0, 0] È//PERFECT USING 1 BYTE WHICH IS -56
US-ASCII [0, 0, 0, 0] //DONT GET IT SEE THIS ITEM FOR LATER
UTF-16 [-2, -1, 0, -56] È<<>>1 //WHAT IS -2,-1 BYTE USED FOR? I HAVE TRY WITH OTHER EXAMPLES AND THEY ALWAYS APPEAR AM I LOSING TWO BYTES HERE??
UTF-8 [-61, -120, 0, 0] 2 È //SEEMS TO MY CHARACTER NEEDS TWO BYTES?? I THOUGHT THAT CODE=200 WOULD REQUIRE ONLY ONE
getBytes
[-61, -120]//OK MY UTF-8 REPRESENTATION
ISO-8859-1 [-56]//OK
US-ASCII [63]//OK BUT WHY WHEN I ENCODE IN ASCCI DOESNT GET ANY BYTE ENCODED?
UTF-16 [-2, -1, 0, -56]//AGAIN WHAT ARE -2,-1 IN THE LEADING BYTES?
UTF-8 [-61, -120]//OK

У меня есть попытка

System.out.println(new String(new byte[]{-1,-2},"UTF-16"));//SIMPLE "" I AM WASTING THIS 2 BYTES??

В резюме.

  1. Почему у UTF-16 всегда есть два старших байта?новый байт [] {- ​​1, -2}

  2. Почему, когда я кодирую "È", я не получаю никаких байтов в ASCCI Charset, но когда я делаю get.getBytes (StandardCharsets.US_ASCII)я получаю {63}?

  3. Java использует UTF-16, но в моем случае UTF-8 зависит от платформы ??

Извините, если этосообщение обсуждает

Окружающая среда

Windows 7 64 Bits Netbeans 8.2 with Java 1.8.0_121

Ответы [ 2 ]

1 голос
/ 10 марта 2019

Первый вопрос

По первому вопросу: эти байты являются кодом спецификации, и они задают порядок байтов (в порядке наименьшего или самого старшего) многобайтового кодирования, такого как UTF-16.

Второй вопрос

Каждый символ ASCII может быть закодирован как один байт в UTF-8. Но ASCII - это не 8-битная кодировка, она использует 7 бит для каждого символа. И на самом деле, все символы Unicode с кодовыми точками> = 128 требуют как минимум два байта. (Причина в том, что вам нужен способ различать 200 и многобайтовую кодовую точку, первый байт которой равен 200. UTF-8 решает эту проблему, используя байты> = 128 для представления многобайтовых кодовых точек.)

'È' не является символом ASCII, поэтому он не может быть представлен в ASCII. Это объясняет второй вывод: 63 является ASCII для символа '?'. И действительно, Javadoc для метода getBytes(Charset) указывает, что не отображаемый ввод отображается в «массив байтов замены по умолчанию», в данном случае «?». С другой стороны, чтобы получить первый байтовый массив ASCII, вы напрямую использовали CharsetEncoder, который является более низкоуровневым API и не выполняет такие автоматические замены. (Когда вы проверили бы результат метода encode, вы обнаружили бы, что он возвратил экземпляр CoderResult, представляющий ошибку.)

Третий вопрос

Java 8 String s использует UTF-16 для внутреннего использования, но при обмене данными с другим программным обеспечением могут ожидаться другие кодировки, такие как UTF-8. Метод Charset.defaultCharset() возвращает набор символов по умолчанию для виртуальной машины, который зависит от локали и набора символов операционной системы, а не от кодировки, используемой внутри строк Java.

1 голос
/ 10 марта 2019

Давайте немного вернемся назад ...

В текстовых типах данных Java используется кодировка символов UTF-16 набора символов Unicode. (Как и VB4 / 5/6 / A / Script, JavaScript, .NET,….) Вы можете увидеть это в различных операциях, которые вы выполняете со строковым API: индексация, длина,….

Библиотеки поддерживают преобразование типов текстовых данных и байтовых массивов с использованием различных кодировок. Некоторые из них классифицируются как «Extended ASCII», но указывается, что это очень плохая замена для именования фактически используемой кодировки символов.

Некоторые операционные системы позволяют пользователю назначать кодировку символов по умолчанию. (Большинство пользователей, тем не менее, не знают или не заботятся.) Java пытается это понять. Это полезно только тогда, когда программа понимает, что ввод от пользователя - это кодировка символов или что вывод должен быть. В этом столетии пользователи, работающие с текстовыми файлами, предпочитают использовать определенную кодировку, передавать их без изменений по всем системам, не ценят преобразования с потерями и, следовательно, не используют эту концепцию. С точки зрения программы, это никогда не то, что вы хотите, если это не то, что вы хотите.

Если преобразование будет с потерями, у вас есть выбор замены символа (например, «?»), Его опускание или исключение.

Кодировка символов - это карта между кодовой точкой (целым числом) набора символов и одной или несколькими кодовыми единицами в соответствии с определением кодировки. Кодовой единицей является фиксированный размер, и количество кодовых единиц, необходимых для кодовой точки, может варьироваться в зависимости от кодовой точки.

В библиотеках, как правило, бесполезно иметь массив единиц кода, поэтому они предпринимают дальнейшие шаги по преобразованию в / из массива байтов. byte значения варьируются от -128 до 127, однако это интерпретация Java как 8-битные целые числа, дополняющие два. Поскольку под байтами понимается кодировка текста, значения будут интерпретироваться в соответствии с правилами кодировки символов.

Поскольку некоторые кодировки Unicode имеют кодовые единицы длиной более одного байта, порядок байтов становится важным. Итак, на уровне байтового массива есть UTF-16 Big Endian и UTF-16 Little Endian. При передаче текстового файла или потока вы отправляете байты, а также имеете общие знания о кодировке. Эти «метаданные» необходимы для понимания. Итак, UTF-16BE или UTF-16LE, например. Чтобы сделать это немного проще, Unicode позволяет некоторым метаданным в начале файла или потока указывать порядок байтов. Это называется меткой порядка байтов (BOM). Таким образом, внешние метаданные могут совместно использовать кодировку (скажем, UTF-16), в то время как внутренние метаданные разделяют порядок байтов. Юникод позволяет присутствовать в спецификации, даже если порядок следования байтов не имеет значения, например, UTF-8. Таким образом, если понимание состоит в том, что байты являются текстовым кодированием с любой кодировкой Unicode и присутствует спецификация, тогда очень просто выяснить, какая это кодировка Unicode и каков порядок байтов, если он относительный.

1) Вы видите спецификацию в некоторых ваших выходах кодировки Unicode.

2) È отсутствует в наборе символов ASCII. Что бы произошло в этом случае? Я часто предпочитаю исключение.

3) Система, которую вы использовали для своей учетной записи во время ваших тестов, могла иметь кодировку UTF-8 в качестве кодировки символов по умолчанию. Это важно для того, как вы хотите, и кодировала ваши текстовые файлы на этом система

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...