如何在 Java/Scala 中跳过流中的无效字符?
Posted
技术标签:
【中文标题】如何在 Java/Scala 中跳过流中的无效字符?【英文标题】:How to skip invalid characters in stream in Java/Scala? 【发布时间】:2011-11-09 00:08:03 【问题描述】:例如我有以下代码
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】:您可以通过调用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 中的 the Charsets
class)。
【讨论】:
+1 向我介绍了 StandardCharset。我想要那个很久了。没有了catch (UnsupportedEncodingException e) // never happens
@Thilo:如果你坚持使用 Java 6,那么 Guava 提供了 the Charsets
class,它可以做同样的事情。
注意:如果您正在写入文件,您可能会遇到类似的错误。您也可以在 CharsetEncoder 上设置相同的 onMalformedInput: IGNORE。【参考方案2】:
好吧,如果不是 UTF-8,那就是别的东西。诀窍是找出其他东西是什么,但是如果您只想避免错误,则可以使用没有无效代码的编码,例如latin1
:
Source.fromFile(new File( path), "latin1").getLines()
【讨论】:
不幸的是,有时某些来源提供“主要是 UTF-8”并包含格式错误的输入。在这些情况下,跳过损坏的字符并仍然解码正确的字符可能是可以接受的。【参考方案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)
【讨论】:
以上是关于如何在 Java/Scala 中跳过流中的无效字符?的主要内容,如果未能解决你的问题,请参考以下文章