如何在 Haskell 中高效地写入大文件

How to write big file efficiently in Haskell

你好,我正在尝试及时 manner.Is 编写一个 ~1GB 文件,有任何推荐 method.Up 直到现在这个过程大约需要几十分钟。我使用 Text 是不是错了,我应该使用 ByteString 吗? (我也用过String

    pt="d:\data2.csv"
    cnt=400000000

    main::IO()
    main=do
        let payload=dat
        writeWithHandle pt dat


    dat::Text
    dat=Data.Text.pack "0744442339"


    writeWithHandle::FilePath->Text->IO()
    writeWithHandle path tx=do
        handle<-openFile path WriteMode
        writeTimes cnt handle dat

    writeTimes::Int->Handle->Text->IO()
    writeTimes cnt handle payload= forM_ ([0..cnt])  (\x->Data.Text.IO.hPutStrLn handle payload)

我不明白为什么我用的是 minutes.Initially 的 writeFile,但我认为这意味着要不断地打开和关闭 file对于每一行,所以我使用 appendFile 无济于事。

我建议为此使用生成器,这是填充缓冲区的有效方法,并且可以直接写入句柄。

#!/usr/bin/env stack
-- stack --resolver ghc-8.6.4 script
{-# LANGUAGE OverloadedStrings #-}
import Data.ByteString.Builder (Builder, hPutBuilder)
import Data.Foldable (fold)
import System.IO (IOMode (WriteMode), withBinaryFile)

pt :: FilePath
pt = "data2.csv"

cnt :: Int
cnt = 400000000

main :: IO ()
main = writeWithHandle pt dat

dat :: Builder
dat = "0744442339"

writeWithHandle :: FilePath -> Builder -> IO ()
writeWithHandle path tx =
  withBinaryFile path WriteMode $ \h ->
  hPutBuilder h $ makeBuilder cnt tx

makeBuilder :: Int -> Builder -> Builder
makeBuilder cnt payload = fold $ replicate cnt $ payload <> "\n"

如果愿意,您可以将 payload 保留为 Text 值,然后使用 encodeUtf8Builder.

转换为 Builder