Почему Java String.getBytes() использует "ISO-8859-1"
из java.lang.StringCoding:
String csn = (charsetName == null) ? "ISO-8859-1" : charsetName;
Это то, что используется в Java.lang.getBytes(), в linux jdk 7
Мне всегда казалось, что UTF-8 является кодировкой по умолчанию?
Спасибо
Ответы
Ответ 1
Это немного сложно...
Java пытается использовать кодировку символов по умолчанию для возврата байтов с помощью String.getBytes().
- Кодировка по умолчанию предоставляется с помощью свойства system file.encoding.
- Это кэшируется, и нет смысла изменять его с помощью System.setProperty(..) после запуска JVM.
- Если свойство file.encoding не сопоставляется с известной кодировкой, то указывается UTF-8.
.... Вот сложная часть (которая, вероятно, никогда не войдет в игру)....
Если система не может декодировать или кодировать строки с использованием кодировки по умолчанию (UTF-8 или другой), тогда будет отказ от ISO-8859-1. Если резервное копирование не работает... система не сработает!
.... Действительно... (gasp!)... Может ли это сбой, если моя указанная кодировка не может быть использована, а UTF-8 или ISO-8859-1 также непригодны для использования?
Да. Исходные комментарии Java ссылаются на метод StringCoding.encode(...):
//Если мы не можем найти ISO-8859-1 (требуемая кодировка), то с установкой все серьезно ошибочно.
... и затем он вызывает System.exit(1)
Итак, почему существует намеренный отказ от ISO-8859-1 в методе getBytes()?
Возможно, хотя и не вероятно, что JVM-пользователи могут не поддерживать декодирование и кодирование в UTF-8 или кодировку, указанную при запуске JVM.
Затем используется ли по умолчанию кодировка по умолчанию в классе String во время getBytes()?
Нет. Однако лучший вопрос - это...
Предоставляет ли String.getBytes() то, что он promises?
Контракт, определенный в Javadoc, верен.
Поведение этого метода, когда эта строка не может быть закодирована в default charset не указан. Класс CharsetEncoder
должен быть используется, когда требуется больше контроля над процессом кодирования.
Хорошие новости (и лучший способ сделать что-то)
Всегда рекомендуется указывать "ISO-8859-1" или "US-ASCII" или "UTF-8" или любой другой набор символов, который вы хотите использовать при преобразовании байтов в строки "наоборот" - если только вы не ранее получили кодировку по умолчанию и сделали 100% уверенным, что это тот, который вам нужен.
Используйте этот метод вместо:
public byte[] getBytes(String charsetName)
Чтобы найти значение по умолчанию для вашей системы, просто используйте:
Charset.defaultCharset()
Надеюсь, что это поможет.
Ответ 2
Без параметров String.getBytes()
метод по умолчанию не использует ISO-8859-1. Он будет использовать кодировку платформы по умолчанию, если это можно определить. Если, однако, это либо отсутствует, либо является непризнанной кодировкой, оно возвращается к ISO-8859-1 как "по умолчанию по умолчанию".
Вы должны очень редко видеть это на практике. Обычно стандартное кодирование платформы будет обнаружено правильно.
Однако я настоятельно рекомендую вам указать явное кодирование символов каждый раз, когда вы выполняете операцию кодирования или декодирования. Даже если вы хотите использовать платформу по умолчанию, укажите это явно.
Ответ 3
Что по соображениям совместимости.
Исторически, все java-методы в Windows и Unix, не определяющие кодировку, использовали общий в то время, то есть "ISO-8859-1"
.
Как упоминалось Isaac и javadoc, используется кодировка платформы по умолчанию (см. Charset.java):
594 public static Charset defaultCharset() {
595 if (defaultCharset == null) {
596 synchronized (Charset.class) {
597 String csn = AccessController.doPrivileged(
598 new GetPropertyAction("file.encoding"));
599 Charset cs = lookup(csn);
600 if (cs != null)
601 defaultCharset = cs;
602 else
603 defaultCharset = forName("UTF-8");
604 }
605 }
606 return defaultCharset;
607 }
Всегда указывать кодировку при выполнении строки в байтах или байтах для преобразования строк.
Даже если, как и в случае String.getBytes()
, вы все равно находите не устаревший метод, не принимающий кодировку (большинство из них были устаревшими при появлении Java 1.1). Точно так же, как и с контентом, формат платформы не имеет значения, что актуально для нормы формата хранения.
Ответ 4
Разработайте ответ на Skeet (который, конечно, правильный)
В java.lang.String source getBytes()
вызывает StringCoding.encode(char[] ca, int off, int len)
, который имеет в своей первой строке:
String csn = Charset.defaultCharset().name();
Затем (не сразу, но абсолютно) он вызывает static byte[] StringEncoder.encode(String charsetName, char[] ca, int off, int len)
, куда приходит строка, которую вы цитируете, - передавая как charsetName csn - поэтому в этой строке charsetName
будет будет кодировка по умолчанию если он существует.