gpt4 book ai didi

haskell - 迭代 I/O : need to know file size beforehand

转载 作者:行者123 更新时间:2023-12-04 19:18:26 27 4
gpt4 key购买 nike

假设我需要解析一个以三个 4 字节魔数(Magic Number)开头的二进制文件。其中两个是固定字符串。然而,另一个是文件的长度。

{-# LANGUAGE OverloadedStrings #-}
module Main where

import Data.Attoparsec
import Data.Attoparsec.Enumerator
import Data.Enumerator hiding (foldl, foldl', map, head)
import Data.Enumerator.Binary hiding (map)
import qualified Data.ByteString as S
import System

main = do
f:_ <- getArgs
eitherStat <- run (enumFile f $$ iterMagics)
case eitherStat of
Left _err -> putStrLn $ "Not a beam file: " ++ f
Right _ -> return ()

iterMagics :: Monad m => Iteratee S.ByteString m ()
iterMagics = iterParser parseMagics

parseMagics :: Parser ()
parseMagics = do
_ <- string "FOR1"
len <- big_endians 4 -- need to compare with actual file length
_ <- string "BEAM"
return ()

big_endians :: Int -> Parser Int
big_endians n = do
ws <- count n anyWord8
return $ foldl1 (\a b -> a * 256 + b) $ map fromIntegral ws

如果声明的长度与实际长度不匹配,理想情况下是 iterMagics应该返回一个错误。但是如何?是将实际长度作为参数传递的唯一方法吗?这是迭代式的方式吗?对我来说不是很增量:)

最佳答案

这可以通过枚举轻松完成。首先读取三个 4 字节魔数(Magic Number),然后对余数运行内部迭代器。如果您使用的是 iteratee ,它看起来或多或少是这样的:

parseMagics :: Parser ()
parseMagics = do
_ <- string "FOR1"
len <- big_endians 4 -- need to compare with actual file length
_ <- string "BEAM"
return len

iterMagics :: Monad m => Iteratee S.ByteString m (Either String SomeResult)
iterMagics = do
len <- iterParser parseMagics
(result, bytesConsumed) <- joinI $ takeUpTo len (enumWith iterData I.length)
if len == bytesConsumed
then return $ Right result
else return $ Left "Data too short"

在这种情况下,如果文件太长,它不会抛出错误,但会停止读取。您可以修改它以相当容易地检查该条件。我不认为 Enumerator 具有模拟功能 enumWith ,因此您可能需要手动计算字节数,但同样的原则也适用。

可能更实用的方法是在运行枚举器之前检查文件大小,然后将其与 header 中的值进行比较。您需要将文件大小或文件路径作为参数传递给迭代器(但不是解析器)。
import System.Posix

iterMagics2 filepath = do
fsize <- liftIO . liftM fileSize $ getFileStatus filepath
len <- iterParser parseMagics

关于haskell - 迭代 I/O : need to know file size beforehand,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6522349/

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