performance - 如何在 Haskell 中高效地写入大文件
问题描述
您好,我正在尝试及时写入~1GB
文件。有没有推荐的方法。到目前为止,该过程大约需要几十分钟。我使用错了我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)
我不明白为什么它需要花费数十分钟的时间。最初我正在使用writeFile
,但我认为这将意味着不断打开和关闭file
每一行,所以我过去appendFile
无济于事。
解决方案
我建议为此使用 Builder,这是一种填充缓冲区的有效方法,并且可以直接写入 Handle。
#!/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
为值,然后转换为using 。Text
Builder
encodeUtf8Builder
推荐阅读
- azure - 如何使用数据流在 blob 存储中获取 JSON 数组
- android - 从锁定屏幕中的通知打开通话活动
- groovy - Groovy 捕获父异常但不是子异常
- javascript - 调用初始 res.render 后向 EJS 发送数据?
- reactjs - 从 API 加载数据后 PrimeReact Select Item 为空
- c++ - 如何让 QtCreator FakeVim 在文件保存时用空格替换 TABS?
- gstreamer - 通过 RTSP 发送 jpeg 图像(运动 jpeg) - gStreamer
- python - 使用 sqlalchemy 时如何选择特定列?
- javascript - 错误:javascript 错误:在使用 removeAttribute() 的参数列表后丢失)不起作用 Selenium 和 Java
- javascript - 禁用自动调节时机器人没有响应