haskell管道 - 如何在字节串管道上重复执行takeWhile操作?

时间:2016-06-04 15:37:09

标签: haskell streaming haskell-pipes

我要做的是使用takeWhile将字节串分割为某个字符。

import qualified Data.ByteString.Internal as BS (c2w, w2c)
import Pipes
import Pipes.ByteString as PB
import Pipes.GZip
import Pipes.Prelude as PP
import System.IO

newline = BS.c2w '\n'

splitter = PB.takeWhile (\myWord -> myWord /= newline)

myPipe fileHandle = PP.toListM $ decompress fileProducer >-> splitter
  where
    fileProducer = PB.fromHandle fileHandle       

run = do
  dat <- withFile "somefile.blob" ReadMode myPipe
  pure dat

这让我获得了第一线,但我真正想要的是一次有效地将每个块产生到一个换行符。我该怎么做?

2 个答案:

答案 0 :(得分:3)

@Michael回答很好。我只想说明一些 正在进行的使用模式。

(。{3}}提供<.lhs)

首先进口一些:

 {-# LANGUAGE OverloadedStrings, NoMonomorphismRestriction #-}

 import Pipes
 import qualified Pipes.Prelude as PP
 import qualified Pipes.Group as PG
 import qualified Pipes.ByteString as PB
 import qualified Pipes.GZip as GZip
 import qualified Data.ByteString as BS
 import Lens.Family (view, over)
 import Control.Monad
 import System.IO

如果查看Pipes.ByteString和Pipes.GZip中的函数 你会发现它们都属于以下类型模式:

  1. 制片人...... - &gt; FreeT(制片人......)......
  2. FreeT(制片人......)...... - &gt;制片人......
  3. 镜头&#39; (制片人......)(FreeT(制片人......)......)
  4. 制片人...... - &gt;制片人......
  5. 每个类别中的功能示例:

    1. PB.words
    2. PG.concats
    3. PB.linesPB.chunksOfPB.splits,...
    4. GZip.compressGZip.decompress
    5. 以下是如何使用PB.words将输入流拆分为单词:

       prod = yield "this is\na test\nof the pipes\nprocessing\nsystem"
      
       t1 = runEffect $ (PG.concats . PB.words) prod >-> PP.print
      

      使用类型3的功能 - 例如PB.lines,只需使用view即可 Lens'获取类型1的函数,然后使用PG.concats撰写:

       t2a = runEffect $ (PG.concats . view PB.lines) prod >-> PP.print
      
       t2b h = (PG.concats . view PB.lines) (PB.fromHandle h) >-> PP.print
      
       run2 = withFile "input" ReadMode (runEffect . t2b)
      

      对于制片人 - &gt;生产者功能,只需使用普通功能应用程序:

       t3 h = GZip.decompress (PB.fromHandle h) >-> PP.print
      
       run3 = withFile "input.gz" ReadMode (runEffect . t3)
      
       t4 h = GZip.decompress (PB.fromHandle h) >-> PP.map BS.length >-> PP.print
      
       run4 = withFile "big.gz" ReadMode (runEffect . t4)
      

      首先解压缩然后按行分割,我们嵌套函数 应用程序:

       t5 h = (PG.concats . view PB.lines) ( GZip.decompress (PB.fromHandle h) )
                >-> PP.map BS.length >-> PP.print
      
       run5 = withFile "input.gz" ReadMode (runEffect . t5)
      

答案 1 :(得分:2)

安排

ClientConnectionpipes-bytestring,以便反复打破pipes-group会产生Producer ByteString m rFreeT (Producer ByteString m) m r在这里可以理解为FreeT,因此结果可以被认为是'一连串的bytestring-producer段返回r'。这样,如果其中一个段长度为10千兆字节,we still have streaming rather than a 10 gigabyte strict bytestring

在我看来你想要在换行符上打破bytestring生成器,但是我不知道你是否想要保留换行符。如果你将它们抛弃,这与将bytestring生成器与A_Succession_Of分开,然后将每个从属生成器连接成一个严格的字节串 - 单独的行相同。我在下面写了view PB.lines。这很简单,但只使用accumLines将花哨的Lens.view镜头变成常规功能。 (许多操作在PB.lines中写成镜头,因为它们可以重复用于其他目的,尤其是解析pipes-bytestring恩惠的生产者。)

pipes

理想情况下,您不会在每个换行符处写一个新的字节串。是否必须取决于你将如何处理这些线。