Конструктори безпечного кодування
Отримати Java, щоб належним чином повідомляти вас про помилки кодування, досить складно. Ви повинні використовувати найбільш багатослівний і, на жаль, найменш використовуваний з чотирьох альтернативних конструкторів для кожного з них, InputStreamReader
і OutputStreamWriter
отримати належний виняток щодо кодування.
Для файлового вводу-виводу завжди переконайтеся, що завжди використовуєте як другий аргумент як для аргументу, так OutputStreamWriter
і InputStreamReader
для фантазійного кодера:
Charset.forName("UTF-8").newEncoder()
Є й інші навіть більш вигадливі можливості, але жодна з трьох простих можливостей не працює для передачі винятків. Вони роблять:
OutputStreamWriter char_output = new OutputStreamWriter(
new FileOutputStream("some_output.utf8"),
Charset.forName("UTF-8").newEncoder()
);
InputStreamReader char_input = new InputStreamReader(
new FileInputStream("some_input.utf8"),
Charset.forName("UTF-8").newDecoder()
);
Що стосується бігу з
$ java -Dfile.encoding=utf8 SomeTrulyRemarkablyLongcLassNameGoeShere
Проблема полягає в тому, що при використанні повної форми аргументу кодера для потоків символів ви не зможете пропустити проблеми з кодуванням.
Довший приклад
Ось довший приклад, цей, який керує процесом замість файлу, де ми просуваємо два різні потоки вхідних байтів і один вихідний потік байтів у всі потоки символів UTF-8 з повною обробкою винятків :
Process
slave_process = Runtime.getRuntime().exec("perl -CS script args");
OutputStream
__bytes_into_his_stdin = slave_process.getOutputStream();
OutputStreamWriter
chars_into_his_stdin = new OutputStreamWriter(
__bytes_into_his_stdin,
Charset.forName("UTF-8").newEncoder()
);
InputStream
__bytes_from_his_stdout = slave_process.getInputStream();
InputStreamReader
chars_from_his_stdout = new InputStreamReader(
__bytes_from_his_stdout,
Charset.forName("UTF-8").newDecoder()
);
InputStream
__bytes_from_his_stderr = slave_process.getErrorStream();
InputStreamReader
chars_from_his_stderr = new InputStreamReader(
__bytes_from_his_stderr,
Charset.forName("UTF-8").newDecoder()
);
Тепер у вас є три потоку символів, все піднімають виняток при кодуванні помилок, відповідно називається chars_into_his_stdin
, chars_from_his_stdout
і chars_from_his_stderr
.
Це лише трохи складніше, ніж те, що потрібно для вашої проблеми, рішення якої я дав у першій половині цієї відповіді. Ключовим моментом є те, що це єдиний спосіб виявити помилки кодування.
Тільки не давайте мені почати про PrintStream
винятки з їжі.
InputStreamReader char_input = new InputStreamWriter
слід читати:,InputStreamReader char_input = new InputStreamReader
іInputStreamReader
конструктор бере aCharsetDecoder
, а не aCharsetEncoder
.