Как пропускать недопустимые символы в потоке в Java/Scala?
Например, у меня есть следующий код
Source.fromFile(new File( path), "UTF-8").getLines()
и генерирует исключение
Exception in thread "main" java.nio.charset.MalformedInputException: Input length = 1
at java.nio.charset.CoderResult.throwException(CoderResult.java:260)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:319)
Мне все равно, если некоторые строки не были прочитаны, но как пропустить недопустимые символы и продолжить чтение строк?
Ответы
Ответ 1
Вы можете влиять на то, что декодер charset обрабатывает недопустимый ввод, вызывая CharsetDecoder.onMalformedInput
.
Обычно вы никогда не увидите объект CharsetDecoder
напрямую, потому что он будет создан за кулисами для вас. Поэтому, если вам нужен доступ к нему, вам нужно будет использовать API, который позволяет вам напрямую указывать CharsetDecoder
(а не только имя кодировки или Charset
).
Самый простой пример такого API - InputStreamReader
:
InputStream in = ...;
CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder();
decoder.onMalformedInput(CodingErrorAction.IGNORE);
Reader reader = new InputStreamReader(in, decoder);
Обратите внимание, что этот код использует класс Java 7 StandardCharsets
, для более ранних версий вы можете просто заменить его Charset.forName("UTF-8")
(или используйте класс Charsets
из Guava).
Ответ 2
Хорошо, если это не UTF-8, это нечто другое. Трюк заключается в том, чтобы узнать, что это такое, но если вы хотите избежать ошибок, вы можете использовать кодировку, которая не имеет неверных кодов, например latin1
:
Source.fromFile(new File( path), "latin1").getLines()
Ответ 3
У меня была аналогичная проблема, и один из Scala встроенных кодеков помогло:
Source.fromFile(new File(path))(Codec.ISO8859).getLines()
Ответ 4
Если вы хотите избежать недопустимых символов с помощью Scala, я обнаружил, что это сработало для меня.
import java.nio.charset.CodingErrorAction
import scala.io._
object HelloWorld {
def main(args: Array[String]) = {
implicit val codec = Codec("UTF-8")
codec.onMalformedInput(CodingErrorAction.REPLACE)
codec.onUnmappableCharacter(CodingErrorAction.REPLACE)
val dataSource = Source.fromURL("https://www.foo.com")
for (line <- dataSource.getLines) {
println(line)
}
}
}