7

我必须解析一个文件,实际上必须先阅读它,这是我的程序:

import qualified Data.ByteString.Char8 as B
import System.Environment    

main = do
 args      <- getArgs
 let path  =  args !! 0
 content   <- B.readFile path
 let lines = B.lines content
 foobar lines 

 foobar :: [B.ByteString] -> IO()
 foobar _ = return ()

但是,编译后

> ghc --make -O2 tmp.hs 

使用 7G 文件调用时,执行会出现以下错误。

> ./tmp  big_big_file.dat
> tmp: {handle: big_big_file.dat}: hGet: illegal ByteString size (-1501792951): illegal operation

感谢您的回复!

4

2 回答 2

9

ByteStrings的长度为Int。如果Int是 32 位,则 7GB 文件将超出范围,Int并且缓冲区请求的大小将错误,并且很容易请求负大小。

readFile将文件大小转换Int为缓冲区请求的代码

readFile :: FilePath -> IO ByteString
readFile f = bracket (openBinaryFile f ReadMode) hClose
    (\h -> hFileSize h >>= hGet h . fromIntegral)

如果溢出,“非法 ByteString 大小”错误或分段错误是最可能的结果。

如果可能的话,使用lazy ByteStrings 来处理那么大的文件。在您的情况下,您几乎必须使其成为可能,因为使用 32 位s,不可能创建Int7GB 。ByteString

如果需要处理的行是 strict ByteString,并且没有行过长,可以通过 lazyByteString来实现

import qualified Data.ByteString.Lazy.Char8 as LC
import qualified Data.ByteString.Char8 as C

main = do
    ...
    content <- LC.readFile path
    let llns = LC.lines content
        slns = map (C.concat . LC.toChunks) llns
    foobar slns

但是如果你可以修改你的处理来处理惰性ByteStrings,那总体上可能会更好。

于 2012-04-04T13:42:35.020 回答
5

StrictByteString仅支持最多 2 GiB 的内存。您需要使用lazyByteString才能使其工作

于 2012-04-04T13:44:30.733 回答