Fop*_*tin 7 parsing haskell bytestring readfile
我必须解析一个文件,确实必须先读取它,这是我的程序:
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 ()
Run Code Online (Sandbox Code Playgroud)
但是,在汇编之后
> ghc --make -O2 tmp.hs
Run Code Online (Sandbox Code Playgroud)
使用7Gigabyte文件调用时执行会发生以下错误.
> ./tmp big_big_file.dat
> tmp: {handle: big_big_file.dat}: hGet: illegal ByteString size (-1501792951): illegal operation
Run Code Online (Sandbox Code Playgroud)
谢谢你的回复!
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)
Run Code Online (Sandbox Code Playgroud)
如果溢出,"非法字节串大小"错误或分段错误是最可能的结果.
如果可能的话,使用lazy ByteString来处理那些大的文件.在你的情况下,你几乎必须使它成为可能,因为32位Ints,7GB ByteString是不可能创建的.
如果您需要对行进行严格ByteString的行处理,并且没有行超长,那么您可以通过lazy ByteString来实现
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
Run Code Online (Sandbox Code Playgroud)
但如果你可以修改你的处理来处理懒惰ByteString,那么整体可能会更好.