2012-11-11 54 views
8

我有一个132 kb的文件(你不能说它很大),我试图从Scala REPL读取它,但我无法读取过去的2048字符,因为它给我一个java.nio.charset.MalformedInputException例外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

不能没有文件确定的,但例外的文件表明它抛出“时输入字节塞克nce对于给定的字符集不合法,或者输入字符序列不是合法的16位Unicode序列。“ (MalformedInputException javadoc

我怀疑在2049是遇到的第一个字符,无论默认的JVM字符编码是否在您的环境中都无效。考虑明确指出文件的字符编码使用其中一个重载fromFile.

如果应用程序是跨平台的,您应该知道JVM上的默认字符编码因平台而异,因此如果您使用您可能希望在启动应用程序时明确将其设置为命令行参数,或者在每次调用时使用适当的过载指定它。

+2

有测试这一个简单的方法:尽量取第一次2049元。然而,这确实不是真正的问题,只是将刚好在'2^11 + 1'字符处的第一个非法字节序列发送到文件中将是非常巧合。 –

+1

这是我尝试的第一件事,整个迭代器上的plak mkString。然后我把它追踪到2048 ... – opensas

4

任何时候在同一个迭代器上调用take两次,所有投注都关闭。迭代器本质上是强制性的,将它们与功能性的习惯用法混合在一起是最好的。在标准库中遇到的大多数迭代器在这方面往往表现得相当好,但一旦使用了takedropfilter等,您就处于未定义的行为状态,而在原则可能发生。

the docs

这是特别重要的要注意的是,除非另有说明, 一个永远不应该要求它的方法后,使用迭代器。两个 最重要的例外也是唯一的抽象方法:nexthasNext ...

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

重用:调用此方法后,应该丢弃 拜访了迭代器,并只使用返回的迭代器。使用 旧迭代器未定义,可能会更改,也可能导致 更改为新迭代器。

所以它可能不值得试图追查这里到底出了什么问题。

+0

我建议从头开始做一个'it.toList'。这样,他将能够获得所有的数据。 – pedrofurla

+0

@pedrofurla:如果他(或她?企鹅头像图像适度裁剪,所以我不知道)没有必要读取整个文件,对或'toStream'。 –

+0

非常真实,特拉维斯。 – pedrofurla

2

如果你只是希望将字节转换为纯拉丁数据:

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

// InputStream: 
io.Source.fromInputStream(System.io)(io.Codec.ISO8859).mkString 
相关问题