安全编码构造函数
使Java正确通知您编码错误是很棘手的。您必须为每一个使用四个替代构造函数中最冗长的(最可惜),最少使用一个,InputStreamReader
并OutputStreamWriter
在编码故障时收到适当的异常。
对于文件I / O,始终确保始终作为第二个参数都使用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
。