【问题标题】:MalformedInputException when trying to read entire file尝试读取整个文件时出现 MalformedInputException
【发布时间】:2012-10-30 22:07:21
【问题描述】:

我有一个 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 个字符...

【问题讨论】:

    标签: file scala file-io


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

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

      来自the docs

      特别重要的是要注意,除非另有说明, 在对迭代器调用方法后,永远不要使用迭代器。他们俩 最重要的例外也是唯一的抽象方法:nexthasNext ...

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

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

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

      【讨论】:

      • 我建议从一开始就使用it.toList。这样,他就能拥有所有的数据。
      • @pedrofurla:对,或者toStream,如果他(或她?企鹅头像图像被适度裁剪,所以我无法判断)不一定需要阅读整个文件。
      【解决方案3】:

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

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

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

      【讨论】:

      • 有一个简单的测试方法:第一次尝试取 2049 个元素。然而,这肯定不是真正的问题——碰巧将第一个非法字节序列恰好在文件中的2 ^ 11 + 1 字符处命中将是一个奇妙的巧合。
      • 那是我尝试的第一件事,对整个迭代器的感叹 mkString。然后我追踪到了 2048 年……
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-08-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多