Как пропустить недопустимые символы в потоке в 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)

мне все равно, если некоторые строки не были прочитаны, но как пропустить недопустимые символы и продолжить чтение строк?

4 ответов


вы можете повлиять на то, как кодировка кодировки обрабатывает недопустимый ввод, вызвав 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") (или использовать the Charsets класс С гуавы).


Ну, если это не UTF-8, это что-то другое. Трюк заключается в том, чтобы выяснить, что это что-то еще, но если все, что вы хотите, это избежать ошибок, вы можете использовать кодировку, которая не имеет недопустимых кодов, таких как latin1:

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

У меня была аналогичная проблема, и один из встроенных кодеков Scala сделал трюк для меня:

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

Если вы хотите избежать недопустимых символов с помощью 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)
    }
  }
}