【问题标题】:Handling Haskell zlib decompression errors处理 Haskell zlib 解压错误
【发布时间】:2014-02-14 04:03:54
【问题描述】:

我有一个字符串x,它可能是gzip 压缩的,也可能不是。使用zlib库,我想尝试解压x——如果成功,函数将返回压缩后的字符串。如果不是(即x 不是 gzip 压缩的)我想简单地返回 x

由于GZip.decompress 生成error 如果应用于非gzip 字符串,我可以使用catch 或类似的,但我特别要求使用zlib 错误处理机制的解决方案。

我如何编写一个函数,比如decompressIfPossible :: ByteString -> ByteString,它具有前面描述的特征?我更喜欢Either String ByteString 来表示错误或解压结果。

注意:这个问题故意不显示研究成果,因为它立即以问答式的方式回答。

【问题讨论】:

    标签: haskell gzip haskell-zlib


    【解决方案1】:

    您需要在这里使用的来自zlib 的函数称为decompressWithErrors。它的值是递归的DecompressStream 数据结构,您可以使用v:fromDecompressStream 折叠成ByteString

    这里有一个完整的例子来说明如何编写你要求的函数:

    import Data.Either
    import Codec.Compression.Zlib.Internal
    import qualified Data.ByteString.Lazy.Char8 as LB
    
    -- | Convert & unfold the custom DecompressStream
    --   error format from zlib to a Either
    decompressStreamToEither :: DecompressStream -> Either String LB.ByteString
    decompressStreamToEither (StreamError _ errmsg) = Left errmsg
    decompressStreamToEither stream@(StreamChunk _ _) = Right $ fromDecompressStream stream
    decompressStreamToEither StreamEnd = Right $ ""
    
    -- | Decompress with explicit error handling
    safeDecompress :: LB.ByteString -> Either String LB.ByteString
    safeDecompress bstr = decompressStreamToEither $ decompressWithErrors gzipOrZlibFormat defaultDecompressParams bstr
    
    -- | Decompress gzip, if it fails, return uncompressed String
    decompressIfPossible :: LB.ByteString -> LB.ByteString
    decompressIfPossible bstr =
        let conv (Left a) = bstr
            conv (Right a) = a
        in (conv . safeDecompress) bstr
    

    请注意,此示例使用 gzipOrZlibFormat 自动检测标头是 zlib 还是 gzip 标头。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多