处理Haskell zlib解压缩错误 [英] Handling Haskell zlib decompression errors
问题描述
我有一个String x
,它可能会或可能不会经过gzip压缩.我想使用 zlib
库来尝试解压缩 x
-如果成功,该函数将返回压缩的String.如果不是这样(即 x
未被gzip压缩),我只想返回 x
.
I have a String x
which may or may not be gzip-compressed. Using the zlib
library, I want to try decompressing x
-- if it succeeds, the function shall return the compressed String. If not (i.e. x
is not gzip-compressed) I want to simply return x
.
如果将 GZip.decompress
应用于非gzip字符串,则会生成 error
,因此我可以使用 catch
或类似的方法,但是我我专门要求使用 zlib
错误处理机制的解决方案.
As GZip.decompress
generates an error
if applied to a non-gzip string, I could use catch
or similar, but I'm specifically asking for a solution that uses the zlib
error handling mechanism.
如何编写函数,例如 decompressIfPossible :: ByteString->具有上述特征的ByteString
?我更喜欢使用 Ether String ByteString
来表示错误或解压缩结果.
How can I write a function, say decompressIfPossible :: ByteString -> ByteString
that has the previously described characteristics? I'd prefer a Either String ByteString
to represent either the error or the decompression result.
注意:该问题有意不显示研究成果,因为它立即以Q& A方式回答.
Note: This question intentionally does not show research effort, as it was immediately answered in a Q&A-style manner.
推荐答案
您需要在此处使用的 zlib
中的函数称为 v:fromDecompressStream
The function from zlib
you need to use here is called decompressWithErrors
. Its value is the recursive DecompressStream
data structure that you can fold to a ByteString
using v:fromDecompressStream
这是如何编写您要求的功能的完整示例:
Here's a full example of how to write the function you asked for:
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
Note that this example uses gzipOrZlibFormat
which automatically detects if the header is a zlib or a gzip header.
这篇关于处理Haskell zlib解压缩错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!