Есть ли простой способ избежать проблем с кодировкой текста?
Есть ли простой способ избежать проблем с кодировкой текста?
Ответы:
Вы действительно не можете избежать проблем с кодировкой текста, но в Apache Commons есть существующие решения:
Reader
кому InputStream
:ReaderInputStream
Writer
кому OutputStream
:WriterOutputStream
Вам просто нужно выбрать кодировку по вашему выбору.
Если вы начинаете со String, вы также можете сделать следующее:
new ByteArrayInputStream(inputString.getBytes("UTF-8"))
ReaderInputStream
реализация потребует меньше памяти - не должно быть необходимости хранить все байты в массиве сразу.
Итак, Reader имеет дело с символами, а InputStream - с байтами. Кодировка определяет, как вы хотите представлять свои символы в байтах, поэтому вы не можете игнорировать проблему. Что касается избежания проблем, мое мнение таково: выберите одну кодировку (например, "UTF-8") и придерживайтесь ее.
Что касается того, как это сделать на самом деле, как уже указывалось, « очевидными именами для этих классов являются ReaderInputStream и WriterOutputStream . » Удивительно, но « они не включены в библиотеку Java », хотя «противоположные» классы, InputStreamReader и OutputStreamWriter, являются включены.
Итак, многие люди придумали свои собственные реализации, включая Apache Commons IO . В зависимости от проблем с лицензированием вы, вероятно, сможете включить библиотеку commons-io в свой проект или даже скопировать часть исходного кода (который можно загрузить здесь ).
Как видите, в документации обоих классов указано, что «все кодировки кодировки, поддерживаемые JRE, обрабатываются правильно».
NB В комментарии к одному из других ответов здесь упоминается эта ошибка . Но это влияет на класс Apache Ant ReaderInputStream ( здесь ), а не на класс Apache Commons IO ReaderInputStream.
Также обратите внимание, что если вы начинаете со String, вы можете пропустить создание StringReader и создать InputStream за один шаг, используя org.apache.commons.io.IOUtils из Commons IO следующим образом:
InputStream myInputStream = IOUtils.toInputStream(reportContents, "UTF-8");
Конечно, вам все равно нужно подумать о кодировке текста, но, по крайней мере, преобразование происходит за один шаг.
new ByteArrayInputStream(report.toString().getBytes("utf-8"))
, который включает размещение двух дополнительных копий отчета в памяти. Если отчет большой - плохой. Смотрите мой ответ.
Использование:
new CharSequenceInputStream(html, StandardCharsets.UTF_8);
Этот способ не требует предварительного преобразования в, String
а затем в byte[]
, который выделяет намного больше памяти кучи, если отчет большой. Он преобразуется в байты на лету, когда поток читается, прямо из StringBuffer.
Он использует CharSequenceInputStream из проекта ввода-вывода Apache Commons.
Очевидные имена для этих классов - ReaderInputStream и WriterOutputStream. К сожалению, они не включены в библиотеку Java. Однако Google - ваш друг.
Я не уверен, что он решит все проблемы с кодировкой текста, которые просто кошмарны.
Есть RFE, но закрытый, исправлять не буду.
Вы не можете избежать проблем с кодировкой текста, но Apache commons-io имеет
Обратите внимание, что это библиотеки, упомянутые в ответе Питера на koders.com, просто ссылки на библиотеку, а не на исходный код.
Вы пытаетесь записать содержимое a Reader
в OutputStream
? Если это так, вам будет легче обернуть OutputStream
в OutputStreamWriter
и записать char
s из в Reader
в Writer
, вместо того, чтобы пытаться преобразовать читателя в InputStream
:
final Writer writer = new BufferedWriter(new OutputStreamWriter( urlConnection.getOutputStream(), "UTF-8" ) );
int charsRead;
char[] cbuf = new char[1024];
while ((charsRead = data.read(cbuf)) != -1) {
writer.write(cbuf, 0, charsRead);
}
writer.flush();
// don't forget to close the writer in a finally {} block
Предупреждение при использовании WriterOutputStream - он не всегда обрабатывает запись двоичных данных в файл должным образом / так же, как обычный выходной поток. У меня была проблема с этим, и мне потребовалось некоторое время, чтобы ее разыскать.
Если вы можете, я бы рекомендовал использовать выходной поток в качестве основы, а если вам нужно писать строки, используйте для этого оболочку OUtputStreamWriter вокруг потока. Гораздо надежнее преобразовать текст в байты, чем наоборот, поэтому, вероятно, WriterOutputStream не является частью стандартной библиотеки Java.
Вы можете использовать Cactoos (без статических методов, только объекты):
Вы можете преобразовать и наоборот:
Для чтения строки в потоке, используя только то, что предоставляет java.
InputStream s = new BufferedInputStream( new ReaderInputStream( new StringReader("a string")));