file - 如何使用 Haskell 分割 110Mo 文件

标签 file haskell file-io io

我有一个类似于 index : label 的文件,index 的值包含 0...100000000 范围内的键> 和 label 可以是任何 String 值,我想将这个包含 110 Mo 的文件拆分为多个切片,每个切片各 100 行,并对每个切片进行一些计算。我怎样才能做到这一点?

123 : "acgbdv"

127 : "ytehdh"

129 : "yhdhgdt"

...

9898657 : "bdggdggd"

最佳答案

如果您使用 String IO,则可以执行以下操作:

import System.IO
import Control.Monad

-- | Process 100 lines
process100 :: [String] -> MyData
-- whatever this function does

loop :: [String] -> [MyData]
loop lns = go [] lns
  where
    go acc []  = reverse acc
    go acc lns = let (this, next) = splitAt 100 lns in go (process100 this:acc) next

processFile :: FilePath -> IO [MyData]
processFile f = withFile f ReadMode (fmap (loop . lines) . hGetContents)

请注意,此函数将静默处理最后一个 block ,即使它不完全是 100 行。

诸如 bytestring 和 text 之类的包通常提供诸如 lineshGetContents 之类的函数,因此您应该能够轻松地将此函数应用于其中的任何一个。

了解您正在处理每个切片的结果非常重要,因为您不想保留该数据超过必要的时间。理想情况下,在计算每个切片后,数据将被完全消耗并且可以被GC。通常,要么将单独的结果组合成单个数据结构(“折叠”),要么单独处理每个结果(可能将一行输出到文件或类似的东西)。如果是折叠,您应该将“循环”更改为如下所示:

loopFold :: [String] -> MyData -- assuming there is a Monoid instance for MyData
loopFold lns = go mzero lns
  where
    go !acc []  = acc
    go !acc lns = let (this, next) = splitAt 100 lns in go (process100 this `mappend` acc) next

loopFold 函数使用 bang 模式(通过“LANGUAGE BangPatterns”编译指示启用)来强制评估“MyData”。根据 MyData 的具体内容,您可能需要使用 deepseq 来确保它得到充分评估。

如果您将每一行写入输出,请保持 loop 不变并更改 processFile:

processFileMapping :: FilePath -> IO ()
processFileMapping f = withFile f ReadMode pf
  where
    pf = mapM_ (putStrLn . show) <=< fmap (loop . lines) . hGetContents

如果您对枚举器/迭代器样式处理感兴趣,这是一个非常简单的问题。如果不知道 process100 正在做什么工作,我就无法给出一个很好的例子,但它会涉及 enumLinestake

是否有必要一次恰好处理 100 行,还是只想分块处理以提高效率?如果是后者,不用担心。您最好一次处理一行,使用实际的折叠函数或类似于 processFileMapping 的函数。

关于file - 如何使用 Haskell 分割 110Mo 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3698404/

相关文章:

android - 创建的文件夹在文件资源管理器中不可见。

php - 无法在 php 中追加文件

Ruby:如何从文件中读取正则表达式,然后使用该正则表达式解析字符串?

haskell - haskell 中的字符串与字符串?

haskell - DefaultSignatures 和相关的类型族

Java - 如何将文件 move 到 zip 文件中?

haskell - $forall : why it doesn't bring deconstructed members in scope? 中的小村庄模板和解构数据

perl - 使用 Perl 将 PDF 文件字节写入文件?

javascript - 是否可以使用 Javascript(不在浏览器中运行)检查磁盘上是否存在文件?

ruby-on-rails - 通过单击按钮完成文件选择时如何测试文件字段?