2012-11-11 78 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 
相關問題