Haskell读/写二进制文件完成工作示例

时间:2015-08-27 15:44:25

标签: haskell io binaryfiles

我希望如果有人提供了一个完整的工作代码,允许在Haskell中执行以下操作:

  

读取一个非常大的32位序列(超过10亿个元素)   从二进制文件到适当容器的int值(例如   当然不是列表,因为性能问题)和每个数字加倍   如果它小于1000(十进制)然后写入结果的32位   int值到另一个二进制文件。我可能不想读全文   内存中二进制文件的内容一次。我想读一个   之前的大块。

我很困惑因为我找不到关于此的文档。 Data.Binary,ByteString,Word8等等,它只是增加了混乱。对C / C ++中的这些问题有非常直接的解决方案。获取所需大小的数组(例如unsigned int),并使用读/写库调用并完成它。在Haskell中,它似乎并不那么容易,至少对我而言。

如果您的解决方案使用主流Haskell(> GHC 7.10)提供的最佳标准软件包而不是某些模糊/过时的软件包,我将不胜感激。

我从这些页面阅读

https://wiki.haskell.org/Binary_IO

https://wiki.haskell.org/Dealing_with_binary_data

2 个答案:

答案 0 :(得分:4)

如果您正在进行二进制 I / O,那么您几乎肯定希望ByteString用于实际的输入/输出部分。查看它提供的hGethPut函数。 (或者,如果您只需要严格的线性访问权限,则可以尝试使用惰性I / O,但很容易出错。)

当然,字节字符串只是一个字节数组;你的下一个问题是将这些字节解释为字符/整数/双精度/它们应该是的其他任何东西。有几个包,但Data.Binary似乎是最主流的。

binary的文档似乎想引导您使用Binary类,您可以编写代码来序列化和反序列化整个对象。但是可以使用Data.Binary.GetData.Binary.Put中的函数来处理单个项目。在那里你会找到诸如getWord32be(get Word32 big-endian)等功能。

我现在没有时间编写一个工作代码示例,但基本上看看我上面提到的函数并忽略其他所有内容,你应该知道一些。

现在有了工作代码:

module Main where

import Data.Word
import qualified Data.ByteString.Lazy as BIN
import Data.Binary.Get
import Data.Binary.Put
import Control.Monad
import System.IO

main = do
  h_in  <- openFile "Foo.bin" ReadMode
  h_out <- openFile "Bar.bin" WriteMode
  replicateM 1000 (process_chunk h_in h_out)
  hClose h_in
  hClose h_out

chunk_size = 1000
int_size = 4

process_chunk h_in h_out = do
  bin1 <- BIN.hGet h_in chunk_size
  let ints1 = runGet (replicateM (chunk_size `div` int_size) getWord32le) bin1
  let ints2 = map (\ x -> if x < 1000 then 2*x else x) ints1
  let bin2 = runPut (mapM_ putWord32le ints2)
  BIN.hPut h_out bin2

我相信,这就是你所要求的。它读取1000个chunk_size字节块,将每个字节转换为Word32列表(因此它一次只能在内存中有chunk_size / 4个整数),是否指定了计算,并写入结果再次退出。

显然,如果你做了这个&#34;对于真实的&#34;你想要EOF检查等等。

答案 1 :(得分:0)

这是一个从stdin

一次处理一行的循环
import System.IO

loop = do b <- hIsEOF stdin
          if b then return ()
               else do str <- hGetLine stdin
                       let str' = ...process str...
                       hPutStrLn stdout str'

现在只需用{4}字节等替换hGetLine

以下是Data.ByteString的I / O部分:

https://hackage.haskell.org/package/bytestring-0.10.6.0/docs/Data-ByteString.html#g:29