8

我有一个 132 kb 的文件(你不能说它很大),我正在尝试从 Scala REPL 中读取它,但我无法读取超过 2048 个字符,因为它给了我一个java.nio.charset.MalformedInputException例外

这些是我采取的步骤:

val it = scala.io.Source.fromFile("docs/categorizer/usig_calles.json") // this is ok
it.take(2048).mkString // this is ok too
it.take(1).mkString // BANG!

java.nio.charset.MalformedInputException: Input length = 1
at java.nio.charset.CoderResult.throwException(CoderResult.java:277)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:338)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)
at java.io.InputStreamReader.read(InputStreamReader.java:184)

知道有什么问题吗?

--

显然问题是文件不是UTF编码的

我将它保存为 UTF 并且一切正常,我只是在迭代器上发出 mkString 并检索文件的全部内容

奇怪的是,错误只引起了传递前 2048 个字符......

4

3 回答 3

5

没有该文件无法确定,但有关异常的文档表明它被抛出“当输入字节序列对于给定的字符集不合法,或者输入字符序列不是合法的 16 位 Unicode 序列时”。( MalformedInputException javadoc )

我怀疑在 2049 处遇到的第一个字符对于您环境中的默认 JVM 字符编码无效。考虑使用重载之一明确说明文件的字符编码fromFile.

如果应用程序将是跨平台的,您应该知道 JVM 上的默认字符编码确实因平台而异,因此如果您使用特定编码进行操作,您要么希望在启动应用程序时将其显式设置为命令行参数,或在每次调用时使用适当的重载指定它。

于 2012-11-11T01:25:39.520 回答
4

如果您只想将字节转换为纯拉丁数据:

// File:
io.Source.fromFile(file)(io.Codec.ISO8859).mkString

// InputStream:
io.Source.fromInputStream(System.io)(io.Codec.ISO8859).mkString
于 2014-06-15T13:35:17.477 回答
4

任何时候你take在同一个迭代器上调用两次,所有的赌注都被取消了。迭代器本质上是必不可少的,将它们与函数式惯用语混合起来充其量是冒险的。您在标准库中遇到的大多数迭代器在这方面往往表现得相当好,但是一旦您使用take, or drop, orfilter等​​,您就处于未定义行为领域,原则上任何事情都可以发生。

文档

特别重要的是要注意,除非另有说明,否则 在调用迭代器方法后绝不应使用迭代器。两个最重要的例外也是唯一的抽象方法:nexthasNext...

def take(n: Int): Iterator[A]...

重用:调用此方法后,应丢弃调用它的迭代器,只使用返回的迭代器。使用旧迭代器是未定义的,可能会发生变化,并且也可能导致对新迭代器的更改。

因此,可能不值得尝试准确找出这里出了什么问题。

于 2012-11-11T01:42:17.253 回答