Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to catch the decompress IOError?

Tags:

haskell

gzip

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?

like image 776
fho Avatar asked Apr 06 '12 11:04

fho


Video Answer


2 Answers

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.)

like image 163
dave4420 Avatar answered Nov 07 '22 18:11

dave4420


You might want to look at spoon, which will allow you to get Nothing if an exception was thrown.

like image 22
Michael Snoyman Avatar answered Nov 07 '22 18:11

Michael Snoyman