将Lazy ByteString转换为严格的ByteString

时间:2011-10-19 00:50:06

标签: haskell lazy-evaluation strict bytestring chunking

我有一个lazy ByteString的函数,我希望返回strict ByteStrings的列表(懒惰应该转移到输出的列表类型)。

import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as L
csVals :: L.ByteString -> [B.ByteString]

我想出于各种原因这样做,several lexing functions需要严格ByteString s,我可以保证在ByteString s的输出中输出严格的csVal s非常小。

如何在没有chunking的情况下“严格”ByteString

Update0

我想要一个懒惰的ByteString,并制作一个包含其所有数据的严格ByteString

5 个答案:

答案 0 :(得分:32)

bytestring包现在导出toStrict函数:

http://hackage.haskell.org/packages/archive/bytestring/0.10.2.0/doc/html/Data-ByteString-Lazy.html#v:toStrict

这可能不是你想要的,但它确实回答了这篇文章标题中的问题:)

答案 1 :(得分:16)

就像上面的评论中所说的@sclv一样,lazy bytestring只是一个严格的字节串列表。有两种方法可以将lazy ByteString转换为strict(来源:haskell mailing list discussion about adding toStrict function) - 来自以下电子邮件主题的相关代码:

首先,相关的图书馆:

import qualified Data.ByteString               as B
import qualified Data.ByteString.Internal      as BI
import qualified Data.ByteString.Lazy          as BL
import qualified Data.ByteString.Lazy.Internal as BLI
import           Foreign.ForeignPtr
import           Foreign.Ptr

方法1(与@sclv相同):

toStrict1 :: BL.ByteString -> B.ByteString
toStrict1 = B.concat . BL.toChunks

方法2:

toStrict2 :: BL.ByteString -> B.ByteString
toStrict2 BLI.Empty = B.empty
toStrict2 (BLI.Chunk c BLI.Empty) = c
toStrict2 lb = BI.unsafeCreate len $ go lb
  where
    len = BLI.foldlChunks (\l sb -> l + B.length sb) 0 lb

    go  BLI.Empty                   _   = return ()
    go (BLI.Chunk (BI.PS fp s l) r) ptr =
        withForeignPtr fp $ \p -> do
            BI.memcpy ptr (p `plusPtr` s) (fromIntegral l)
            go r (ptr `plusPtr` l)

如果需要考虑性能,我建议您查看上面的电子邮件主题。它也有标准基准。在这些基准测试中,toStrict2比toStrict1更快。

答案 2 :(得分:5)

如果有问题的惰性ByteString是< =严格ByteString的最大大小:

toStrict = fromMaybe SB.empty . listToMaybe . toChunks

toChunks使每个块尽可能大(除了可能是最后一个)。

如果懒惰ByteString的大小比严格的ByteString大,那么这是不可能的:这正是lazy ByteStrings的用途。

答案 3 :(得分:0)

您还可以使用blaze-builder从lazy

构建严格的ByteString
toStrict :: BL.ByteString -> BS.ByteString
toStrict = toByteString . fromLazyByteString

必须有效。

答案 4 :(得分:0)

Data.ByteString.Lazy.Char8现在有toStrict和fromStrict函数。