Конструкторы безопасного кодирования
Сложно заставить 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 с полной обработкой исключений :
// this runs a perl script with UTF-8 STD{IN,OUT,ERR} streams
Process
slave_process = Runtime.getRuntime().exec("perl -CS script args");
// fetch his stdin byte stream...
OutputStream
__bytes_into_his_stdin = slave_process.getOutputStream();
// and make a character stream with exceptions on encoding errors
OutputStreamWriter
chars_into_his_stdin = new OutputStreamWriter(
__bytes_into_his_stdin,
/* DO NOT OMIT! */ Charset.forName("UTF-8").newEncoder()
);
// fetch his stdout byte stream...
InputStream
__bytes_from_his_stdout = slave_process.getInputStream();
// and make a character stream with exceptions on encoding errors
InputStreamReader
chars_from_his_stdout = new InputStreamReader(
__bytes_from_his_stdout,
/* DO NOT OMIT! */ Charset.forName("UTF-8").newDecoder()
);
// fetch his stderr byte stream...
InputStream
__bytes_from_his_stderr = slave_process.getErrorStream();
// and make a character stream with exceptions on encoding errors
InputStreamReader
chars_from_his_stderr = new InputStreamReader(
__bytes_from_his_stderr,
/* DO NOT OMIT! */ Charset.forName("UTF-8").newDecoder()
);
Теперь у вас есть три символьных потока, которые все вызывают исключение при ошибках кодирования, соответственно называемые chars_into_his_stdin
, chars_from_his_stdout
и chars_from_his_stderr
.
Это лишь немного сложнее, чем то, что вам нужно для вашей проблемы, решение которой я дал в первой половине этого ответа. Ключевым моментом является то, что это единственный способ обнаружить ошибки кодирования.
Только не начинайте меня с PrintStream
исключений в еде.