gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-02 11:00:22 27 4
gpt4 key购买 nike

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

Read a very large sequence (more than 1 billion elements) of 32-bit int values from a binary file into an appropriate container (e.g. certainly not a list, for performance issues) and doubling each number if it's less than 1000 (decimal) and then write the resulting 32-bit int values to another binary file. I may not want to read the entire contents of the binary file in the memory at once. I want to read one chunk after the previous.

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

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

我从这些页面阅读

https://wiki.haskell.org/Binary_IO

https://wiki.haskell.org/Dealing_with_binary_data

最佳答案

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

当然,字节字符串只是字节数组;你的下一个问题是将这些字节解释为字符/整数/ double /它们应该是什么。有几个软件包可以实现这一点,但 Data.Binary 似乎是最主流的一个。

binary 的文档似乎希望引导您使用 Binary 类,您可以在其中编写代码来序列化和反序列化整个对象。但是您可以使用Data.Binary.GetData.Binary.Put 中的函数来处理单个项目。在那里您将找到诸如 getWord32be(获取 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 字节 block ,将每个 block 转换为 Word32 列表(因此内存中只有 chunk_size/4 个整数,位于一次),执行您指定的计算,并再次将结果写回。

显然,如果您“真正”这样做,您会需要 EOF 检查等。

关于Haskell 读/写二进制文件完整工作示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32253948/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com