Проблемы с кодировкой запутывают и усложняют сами по себе, но помимо этого вы должны помнить точные имена ваших кодировок. Это "utf8"
? Или "utf-8"
? Или, может быть, "utf-8"
? При поиске в Интернете для образцов кода вы увидите все вышеперечисленное. Почему бы просто не называть их константами и использовать Charset.UTF8
?
Java: Почему имена символов не являются константами?
Ответ 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) не делает то же самое, бьет меня.