Конструкторы безопасного кодирования
Заставить 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
конструктор принимает, аCharsetDecoder
неCharsetEncoder
.