我有一个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
?
我想要一个懒惰的ByteString
,并制作一个包含其所有数据的严格ByteString
。
答案 0 :(得分:32)
bytestring
包现在导出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
构建严格的ByteStringtoStrict :: BL.ByteString -> BS.ByteString
toStrict = toByteString . fromLazyByteString
必须有效。
答案 4 :(得分:0)
Data.ByteString.Lazy.Char8现在有toStrict和fromStrict函数。