如何在Java / Scala中跳过流中的无效字符?

例如,我有以下代码

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

它抛出exception

 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) 

我不在乎是否有些行没有被读取,但是如何跳过无效的字符并继续读取行?

您可以通过调用CharsetDecoder.onMalformedInput来影响字符集解码处理无效输入的方式。

通常,您不会直接看到CharsetDecoder对象,因为它将在幕后为您创建。 因此,如果您需要访问它,则需要使用允许您直接指定CharsetDecoder API(而不仅仅是编码名称或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") (或使用Guava中 的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) } } }