Java: Почему имена символов не являются константами?

Проблемы с кодировкой запутывают и усложняют сами по себе, но помимо этого вы должны помнить точные имена ваших кодировок. Это "utf8"? Или "utf-8"? Или, может быть, "utf-8"? При поиске в Интернете для образцов кода вы увидите все вышеперечисленное. Почему бы просто не называть их константами и использовать Charset.UTF8?

Ответ 1

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

Однако есть шесть, которые должны присутствовать, поэтому константы могли быть сделаны для тех, кто давно. Я не знаю, почему они не были.

JDK 1.4 сделал отличную вещь, представив тип Charset. На данный момент они больше не хотели бы предоставлять String-константы, поскольку цель состоит в том, чтобы заставить всех использовать экземпляры Charset. Итак, почему бы не предоставить шесть стандартных констант Charset? Я спросил Мартина Бухгольца, так как он, оказывается, сидит рядом со мной, и он сказал, что не было особо особого основания, за исключением того, что в то время все было по-прежнему наполовину испечено - слишком мало API JDK было дооснащено принять Charset и из тех, которые были, перегрузки Charset обычно выполняются немного хуже.

Печально, что только в JDK 1.6 они окончательно закончили оснащать все с перегрузками Charset. И что эта обратная ситуация с производительностью все еще существует (причина невероятно странная, и я не могу ее объяснить, но связан с безопасностью!).

Короче говоря, просто определите свои собственные константы или используйте класс Guava Charsets, с которым связан Тони Пони (хотя эта библиотека еще не выпущена).

Обновление: a StandardCharsets класс находится в JDK 7.

Ответ 2

Два года спустя и Java 7 StandardCharsets теперь определяют константы для 6 стандартных кодировок.

Если вы застряли на Java 5/6, вы можете использовать константы Guava Charsets, как предложили Кевин Бурриллион и Джон Скит.

Ответ 3

Я бы сказал, что мы можем сделать гораздо лучше, чем это... почему не доступны доступные для доступа кодировки, доступные напрямую? Charset.UTF8 должен быть ссылкой на Charset, а не на имя в виде строки. Таким образом, нам не пришлось бы обрабатывать UnsupportedEncodingException повсюду.

Помните, я также думаю, что .NET выбрал лучшую стратегию, по умолчанию повсюду UTF-8. Затем он испортился, назвав свойство кодировки "операционная система по умолчанию" просто Encoding.Default - это не значение по умолчанию в самой .NET: (

Назад к разглашению о поддержке набора символов Java - почему нет конструктора для FileWriter/FileReader, который принимает Charset? В основном это почти бесполезные классы из-за этого ограничения - вам почти всегда нужен InputStreamReader вокруг a FileInputStream или эквивалент для вывода: (

Медсестра, медсестра - где моя медицина?

EDIT: Мне кажется, что на этот вопрос не ответил. Реальный ответ, по-видимому, либо "никто не думал об этом", либо "кто-то думал, что это плохая идея". Я бы настоятельно рекомендовал, чтобы внутренние классы утилит, содержащие имена или кодировки, избегали дублирования вокруг кодовой базы... Или вы могли бы просто использовать тот, который мы используем в Google.

Ответ 4

В Java 1.7

import java.nio.charset.StandardCharsets

например: StandardCharsets.UTF_8 StandardCharsets.US_ASCII

Ответ 5

Текущее состояние API кодирования оставляет желать лучшего. Некоторые части API Java 6 не принимают Charset вместо строки (в logging, dom.ls, PrintStream; могут быть и другие). Это не значит, что кодировки должны иметь разные канонические имена для разных частей стандартной библиотеки.

Я могу понять, как все добирается до места, где они есть; не уверен, что у меня есть блестящие идеи о том, как их исправить.


Как в стороне...

Вы можете найти имена для реализации Sun Java 6 здесь.

Для UTF-8 канонические значения "UTF-8" для java.nio и "UTF8" для java.lang и java.io. Единственными кодировками, которые спецификация требует поддержки JRE, являются: US-ASCII; ISO-8859-1; UTF-8; UTF-16BE; UTF-16LE; UTF-16.

Ответ 6

Я уже давно определил класс утилиты с константами Charset UTF_8, ISO_8859_1 и US_ASCII.

Кроме того, некоторое время назад (2+ года) я провел простой тест производительности между new String( byte[], Charset ) и new String( byte[], String charset_name ) и обнаружил, что последняя реализация CONSIDERABLY быстрее. Если вы посмотрите под капотом на исходный код, вы увидите, что они действительно следуют совсем по другому пути.

По этой причине я включил утилиту в том же классе

public static String stringFromByteArray (
    final byte[] array,
    final Charset charset
)
{
    try
    {
        return new String( array, charset.name( ) )
    }
    catch ( UnsupportedEncodingException ex )
    {
        // cannot happen
    }
}

Почему конструктор String (byte [], Charset) не делает то же самое, бьет меня.