Чи існує простий спосіб уникнути проблем із кодуванням тексту?
Чи існує простий спосіб уникнути проблем із кодуванням тексту?
Відповіді:
Ви дійсно не можете уникнути вирішення питань кодування тексту, але в Apache Commons є існуючі рішення:
Reader
до InputStream
:ReaderInputStream
Writer
до OutputStream
:WriterOutputStream
Вам просто потрібно вибрати кодування на ваш вибір.
Якщо ви починаєте з рядка, ви також можете зробити наступне:
new ByteArrayInputStream(inputString.getBytes("UTF-8"))
ReaderInputStream
реалізація зажадає менше пам'яті - не повинно бути необхідності зберігати всі байти в масиві одночасно.
Ну, Reader має справу з символами, а InputStream - з байтами. Кодування визначає, як ви хочете представляти своїх символів як байти, тому ви не можете насправді ігнорувати проблему. Що стосується уникнення проблем, то моя думка така: виберіть одну кодировку (наприклад, "UTF-8") і дотримуйтесь її.
Щодо того, як насправді це зробити, як вже зазначалося, " очевидними назвами цих класів є ReaderInputStream і WriterOutputStream . " Дивно, " вони не включені в бібліотеку Java ", хоча "протилежні" класи, InputStreamReader і OutputStreamWriter є включено.
Отже, багато людей придумали власні реалізації, включаючи Apache Commons IO . Залежно від питань ліцензування, ви, ймовірно, зможете включити бібліотеку commons-io до свого проекту або навіть скопіювати частину вихідного коду (який можна завантажити тут ).
Як бачите, в документації обох класів зазначено, що "всі кодування наборів символів, що підтримуються JRE, обробляються правильно".
Примітка. У коментарі до однієї з інших відповідей тут згадується про цю помилку . Але це впливає на клас Apache Ant ReaderInputStream ( тут ), а не на клас Apache Commons IO ReaderInputStream.
Також зауважте, що якщо ви починаєте з рядка, ви можете пропустити створення 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 IO.
Очевидними назвами цих класів є ReaderInputStream та WriterOutputStream. На жаль, вони не входять до бібліотеки Java. Однак Google - ваш друг.
Я не впевнений, що він обійде всі проблеми кодування тексту, які є кошмарними.
Є RFE, але він закритий, не виправляє.
Ви не можете уникнути проблем із кодуванням тексту, але Apache commons-io це робить
Зверніть увагу, що це бібліотеки, про які йдеться у відповіді Петра koders.com, просто посилання на бібліотеку замість вихідного коду.
Ви намагаєтесь записати вміст a Reader
в an OutputStream
? Якщо це так, вам буде легше обернути символ OutputStream
in 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")));