Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Loops 在IO中编写循环的更好方法_Loops_Haskell - Fatal编程技术网

Loops 在IO中编写循环的更好方法

Loops 在IO中编写循环的更好方法,loops,haskell,Loops,Haskell,给定一个png文件,我试图得到它的块偏移量和大小的列表 简言之,由块组成,每个块由三个4字节字段加上一个可变长度字段(块的数据字段)组成。数据字段的大小存储在第一个4字节字段(称为“长度”字段)中 因此,给定当前块的偏移量和大小(ofs,sz),我们可以通过这种方式导出下一个块的偏移量和大小(ofs',sz'): ofs'=ofs+sz 读取sz'偏移量=ofs' 给定初始块的偏移量和大小,在png文件中始终为(0,8),可以在文件中循环,直到到达其末端。我就是这样做的: import Data

给定一个png文件,我试图得到它的块偏移量和大小的列表

简言之,由块组成,每个块由三个4字节字段加上一个可变长度字段(块的数据字段)组成。数据字段的大小存储在第一个4字节字段(称为“长度”字段)中

因此,给定当前块的偏移量和大小(ofs,sz),我们可以通过这种方式导出下一个块的偏移量和大小(ofs',sz'):

ofs'=ofs+sz

读取sz'偏移量=ofs'

给定初始块的偏移量和大小,在png文件中始终为(0,8),可以在文件中循环,直到到达其末端。我就是这样做的:

import Data.Word
import qualified Data.ByteString.Lazy as BS
import Data.Binary.Get

size :: BS.ByteString -> Int -> IO (Int)
size bytes offset = do
    let ln = runGet (do skip offset
                        l <- getWord32be
                        return l)
                    bytes
    return $ 3*4 + fromIntegral ln

offsetSizes :: Int -> BS.ByteString -> [(Int, Int)] -> IO [(Int, Int)]
offsetSizes fLen bytes oss = do
        let (offset, sz) = last oss
            offset' = offset + sz
        sz' <- size bytes offset'
        let nextOffset = offset' + sz'
        if nextOffset < fLen then offsetSizes fLen bytes $ oss ++ [(offset', sz')]
                              else return oss
main = do
    contents <- BS.readFile "myfile.png"
    let fLen = fromIntegral $ BS.length contents :: Int

    ofszs <- offsetSizes fLen contents [(0,8)]
    putStrLn $ "# of chunks: " ++ (show $ length ofszs)
    putStrLn $ "chunks [(offset,size)]: " ++ show ofszs
导入数据.Word
将限定数据.ByteString.Lazy导入为BS
导入Data.Binary.Get
大小::BS.ByteString->Int->IO(Int)
大小字节偏移量=do
设ln=横档(不跳过偏移
l BS.ByteString->[(Int,Int)]->IO[(Int,Int)]
偏移量大小fLen字节oss=do
let(偏移量,sz)=最后一个oss
偏移量'=偏移量+sz

sz'
offsetSizes
被反复输入某个状态(该
(offset,sz)
对)以生成新的对或完成。创建的所有对都被收集到一个列表中

此递归方案由包中的捕获,允许您将
offsetsize
作为

offsetSizes :: Int -> BS.ByteString -> IO [(Int, Int)]
offsetSizes fLen bytes = unfoldrM step (0, 8)
  where
    step (offset, sz) = do
        let offset' = offset + sz
        sz' <- size bytes offset'
        let state' = (offset', sz')
        return $ if offset' + sz' < fLen then Just (state', state') else Nothing
offsetsize::Int->BS.ByteString->IO[(Int,Int)]
offsetSizes fLen bytes=展开步骤(0,8)
哪里
步进(偏移量,sz)=do
设偏移量'=offset+sz

sz'我会使用类似于in
offsetSizes
;此外,您可以编写
let ln=runGet(skip offset>>getWord32be)字节
来简化它。循环并没有那么糟糕。看起来糟糕的是重复的
oss++[(offset',sz')]
,这是低效的。最好使用
(offset',sz')):oss
创建一个反向列表,然后在循环结束后最终将其反向。这还可以避免
最后一个oss
,这很慢。谢谢你的建议,我会尝试的。