Konstruktory bezpiecznego kodowania
Zmuszenie Javy do prawidłowego powiadamiania o błędach kodowania jest trudne. Musisz użyć najbardziej rozwlekłego i, niestety, najmniej używanego z czterech alternatywnych konstruktorów dla każdego z nich InputStreamReader
i OutputStreamWriter
otrzymać odpowiedni wyjątek od usterki kodowania.
W przypadku wejścia / wyjścia pliku zawsze upewnij się, że zawsze używasz drugiego argumentu obu OutputStreamWriter
i InputStreamReader
fantazyjnego argumentu kodera:
Charset.forName("UTF-8").newEncoder()
Istnieją inne, nawet bardziej wyszukane możliwości, ale żadna z trzech prostszych możliwości nie działa w przypadku obsługi wyjątków. Te robią:
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()
);
Jeśli chodzi o bieganie z
$ java -Dfile.encoding=utf8 SomeTrulyRemarkablyLongcLassNameGoeShere
Problem polega na tym, że nie użyje on pełnej formy argumentu kodera dla strumieni znaków, więc ponownie przegapisz problemy z kodowaniem.
Dłuższy przykład
Oto dłuższy przykład, ten zarządzający procesem zamiast plikiem, w którym promujemy dwa różne strumienie bajtów wejściowych i jeden strumień bajtów wyjściowych do strumieni znaków UTF-8 z pełną obsługą wyjątków :
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()
);
Teraz masz trzy strumienie znakowe że wszystko Wyjątek podbicie na błędy kodowania, odpowiednio nazwane chars_into_his_stdin
, chars_from_his_stdout
i chars_from_his_stderr
.
Jest to tylko trochę bardziej skomplikowane niż to, czego potrzebujesz do swojego problemu, którego rozwiązanie podałem w pierwszej połowie tej odpowiedzi. Najważniejsze jest to, że jest to jedyny sposób wykrywania błędów kodowania.
Tylko nie zaczynaj mi o PrintStream
wyjątkach żywieniowych.
InputStreamReader char_input = new InputStreamWriter
powinien przeczytać:,InputStreamReader char_input = new InputStreamReader
aInputStreamReader
konstruktor bierze aCharsetDecoder
, a nieCharsetEncoder
.