Como pular caracteres inválidos no stream em Java / Scala?

Por exemplo, eu tenho o seguinte código

Source.fromFile(new File( path), "UTF-8").getLines() 

e lança exceção

 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) 

Eu não me importo se algumas linhas não foram lidas, mas como pular caracteres inválidos e continuar lendo linhas?

Você pode influenciar a maneira como a decodificação do conjunto de caracteres manipula inputs inválidas chamando CharsetDecoder.onMalformedInput .

Normalmente você nunca verá um object CharsetDecoder diretamente, porque ele será criado nos bastidores para você. Portanto, se você precisar de access, precisará usar a API que permite especificar o CharsetDecoder diretamente (em vez de apenas o nome da codificação ou o Charset ).

O exemplo mais básico dessa API é o InputStreamReader :

 InputStream in = ...; CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder(); decoder.onMalformedInput(CodingErrorAction.IGNORE); Reader reader = new InputStreamReader(in, decoder); 

Observe que esse código usa os StandardCharsets class Java 7, para versões anteriores você pode simplesmente substituí-lo por Charset.forName("UTF-8") (ou usar a class Charsets de Guava ).

Bem, se não é UTF-8, é outra coisa. O truque é descobrir o que essa outra coisa é, mas se tudo que você quer é evitar os erros, você pode usar uma codificação que não tenha códigos inválidos, como latin1 :

 Source.fromFile(new File( path), "latin1").getLines() 

Eu tive um problema semelhante, e um dos codecs internos do Scala fez o truque para mim:

 Source.fromFile(new File(path))(Codec.ISO8859).getLines() 

Se você quiser evitar caracteres inválidos usando o Scala, descobri que isso funcionou para mim.

 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) } } }