使用 Pipes 读写二进制数据 Haskell
Using Pipes to read and write binary data in Haskell
我正在尝试在常量内存中读取和写入非常多的整数。我已经想出如何将整数写入内存,但还没有想出如何读回它们。
import Control.Lens (zoom)
import System.IO (IOMode(..), withFile)
import Pipes
import qualified Pipes.Prelude as P
import qualified Pipes.ByteString as PB
import qualified Pipes.Parse as P
import qualified Pipes.Binary as P
intStream :: Monad m => Proxy x' x () Int m b
intStream = go (0 :: Int) where
go i = yield i >> go (i + 1)
decoder :: Monad m => Int -> P.Parser P.ByteString m [Int]
decoder n = zoom (P.decoded . P.splitAt n) P.drawAll
main :: IO ()
main = do
withFile "ints" WriteMode $ \h -> do
runEffect $ for intStream P.encode >-> P.take 10000 >-> PB.toHandle h
withFile "ints" ReadMode $ \h -> do
xs <- P.evalStateT (decoder 10000000) (PB.fromHandle h)
print xs
我从 Pipes.Binary. However it uses drawAll
which according to the documentation 的文档中获得了解码器功能 drawAll
不是管道的惯用用法,提供用于测试目的。
我的问题是如何修改 decoder
使其不使用 drawAll
从而不会将 xs
的所有值加载到内存中。因此,我可以 P.map print
在从文件中读取的解码 ints
流上打印 xs 列表。
文档说 decoded
是从字节流到解码值流的透镜。我们可以使用 view
from lens
:
从前者中得到后者
decoder :: Monad m => Int -> Producer P.ByteString m a -> Producer Int m ()
decoder n p = void (view P.decoded p) >-> P.take n
main :: IO ()
main = do
withFile "ints" WriteMode $ \h -> do
runEffect $ for intStream P.encode >-> P.take 10000 >-> PB.toHandle h
withFile "ints" ReadMode $ \h -> do
runEffect $ decoder 10000 (PB.fromHandle h) >-> P.print
我对pipes
没有太多经验,我只是跟着这里的类型。该程序似乎按预期运行。
我正在尝试在常量内存中读取和写入非常多的整数。我已经想出如何将整数写入内存,但还没有想出如何读回它们。
import Control.Lens (zoom)
import System.IO (IOMode(..), withFile)
import Pipes
import qualified Pipes.Prelude as P
import qualified Pipes.ByteString as PB
import qualified Pipes.Parse as P
import qualified Pipes.Binary as P
intStream :: Monad m => Proxy x' x () Int m b
intStream = go (0 :: Int) where
go i = yield i >> go (i + 1)
decoder :: Monad m => Int -> P.Parser P.ByteString m [Int]
decoder n = zoom (P.decoded . P.splitAt n) P.drawAll
main :: IO ()
main = do
withFile "ints" WriteMode $ \h -> do
runEffect $ for intStream P.encode >-> P.take 10000 >-> PB.toHandle h
withFile "ints" ReadMode $ \h -> do
xs <- P.evalStateT (decoder 10000000) (PB.fromHandle h)
print xs
我从 Pipes.Binary. However it uses drawAll
which according to the documentation 的文档中获得了解码器功能 drawAll
不是管道的惯用用法,提供用于测试目的。
我的问题是如何修改 decoder
使其不使用 drawAll
从而不会将 xs
的所有值加载到内存中。因此,我可以 P.map print
在从文件中读取的解码 ints
流上打印 xs 列表。
文档说 decoded
是从字节流到解码值流的透镜。我们可以使用 view
from lens
:
decoder :: Monad m => Int -> Producer P.ByteString m a -> Producer Int m ()
decoder n p = void (view P.decoded p) >-> P.take n
main :: IO ()
main = do
withFile "ints" WriteMode $ \h -> do
runEffect $ for intStream P.encode >-> P.take 10000 >-> PB.toHandle h
withFile "ints" ReadMode $ \h -> do
runEffect $ decoder 10000 (PB.fromHandle h) >-> P.print
我对pipes
没有太多经验,我只是跟着这里的类型。该程序似乎按预期运行。