I wrote this code snippet to read a file that may be compressed:
import Codec.Compression.GZip
import IO -- using IO.try
read file = do
let f = L.readFile file
let c = fmap decompress $ f
unzipped <- try c
case unzipped of
Right b -> return b
Left _ -> f
It compiles just fine, but it seems that this is no valid way to handle uncompressed files. Running the code on a compressed file works nice, but a uncompressed file fails with an exception:
*** Exception: Codec.Compression.Zlib: incorrect header check
Any idea on how to make this possible?
You need to import Codec.Compression.Zlib.Internal. Note in particular the section titled “Low-level API to get explicit error reports”.
You will want to use something like this (note untested):
import qualified Codec.Compression.Zlib.Internal as Z
import Control.Arrow (right)
decompressWithoutExceptions :: L.ByteString -> Either Z.DecompressError L.ByteString
decompressWithoutExceptions = finalise
. Z.foldDecompressStream cons nil err
. Z.decompressWithErrors Z.gzipFormat Z.defaultDecompressParams
where err errorCode errorString = Left errorCode
nil = Right []
cons chunk = right (chunk :)
finalise = right L.fromChunks
(I presume you have imported Data.ByteString.Lazy qualified as L.)
You might want to look at spoon, which will allow you to get Nothing
if an exception was thrown.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With