У меня есть клиентский клиент FTP, который возвращает InputStream, указывающий файл. Я хотел бы прочитать файл по строкам с помощью BufferedReader. Проблема заключается в том, что клиент возвращает файл в двоичном режиме, а файл имеет ISO-8859-15.BufferedReader возвращает ISO-8859-15 String - как преобразовать в строку UTF16?
ответ
Если файл/поток/what действительно содержит ISO-8859-15 закодированный текст, вам просто нужно указать, что при создании InputStreamReader:
BufferedReader br = new BufferedReader(
new InputStreamReader(ftp.getInputStream(), "ISO-8859-15"));
Затем readLine()
создаст допустимые строки в естественной кодировке Java (которая является UTF-16, а не UTF-8).
Я уверен, что, если вы не используете форму конструктора, который принимает аргумент энкодера, а не только строка или кодировка, вы не получите исключение из неверного ввода. – tchrist
@tchrist: Вы говорите о конструкторе ISR, который принимает аргумент CharsetDecoder? Правда, все остальные ctors создают декодеры что * заменить * недопустимые символы, а не бросать исключения. Но я не думаю, что декодер ISO-8859-15 когда-либо выдавал исключение. Все возможные значения байтов отображают действительный символ, и это единственный способ обнаружить искаженный –
Да, это правильно. Проблема в том, что вы запрашиваете UTF-8 и не получаете его - * и * не получаете исключения !! Аналогично для вывода, если вы (глупо) по умолчанию используете платформу defa ult, что на Mac по крайней мере заменяет неизменяемые кодовые точки символами '?', опять же без каких-либо предупреждений или исключений. Я привык к намного более безопасному поведению с Perl в этих областях, а значения по умолчанию Java просто сломаны. Из-за этого вся наша кодовая база (часть Java, а не часть Perl) пронизана неприятными ошибками. Почти заставляет вас хотеть обезглавливать std Java libs. *Почти*. ☺ – tchrist
Исходная строка находится в ISO-8859-15, поэтому поток байтов, считываемый вашим InputStreamReader, будет в этой кодировке. Поэтому прочтите эту кодировку (укажите это в конструкторе InputStreamReader). Это сообщает InputStreamReader, что входящий поток байтов находится в ISO-8859-15 и выполняет соответствующие преобразования в байтах.
Теперь он будет в стандартном формате Java UTF-16, и вы сможете делать все, что пожелаете.
Я думаю, что текущая проблема заключается в том, что вы читаете ее с использованием кодировки по умолчанию (не указывая кодировку в InputStreamReader), а затем пытаетесь ее преобразовать, и к тому времени уже слишком поздно.
Использование поведения по умолчанию для такого рода классов часто заканчивается печалью. Это хорошая идея, чтобы указать кодировку везде, где можно, и/или по умолчанию кодировку VM с помощью -Dfile.encoding
Продвинутый вопрос почему? –
Должно быть, неправильно, извините, осталось слишком поздно, чтобы отменить :( – Kieran
Вы пробовали:
BufferedReader r = new BufferedReader(new InputStreamReader("ISO-8859-1"))
...
s/b ISO-8859-15, а не ISO-8859-1 – lavinio
Попробуйте это:
BufferedReader br = new BufferedReader(
new InputStreamReader(
ftp.getInputStream(),
Charset.forName("ISO-8859-15")
)
);
String row = br.readLine();
Я не вижу, как здесь работает UTF-8 - Java использует UTF-16 внутренне, а не UTF-8. –
Извините, он должен был сказать UTF-16. Исправлена. – tputkonen