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サイズ」エラーまたはセグメンテーション違反が最も可能性の高い結果です。

可能であれば、lazyByteStringを使用してその大きなファイルを処理します。あなたの場合、32ビットIntでは7GBByteStringを作成することは不可能なので、それを可能にする必要があります。

処理のために行を厳密にする必要があり、ByteString行が極端に長くない場合は、遅延を実行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

しかし、怠惰なものを処理するように処理を変更できる場合は、ByteStringおそらく全体的に優れています。

于 2012-04-04T13:42:35.020 に答える
5

StrictByteStringは最大 2 GiB のメモリのみをサポートします。それが機能するには、 lazyByteStringを使用する必要があります。

于 2012-04-04T13:44:30.733 に答える