2012-04-06 9 views
5

pisałem ten fragment kodu do odczytu pliku, który może być skompresowany:Jak złapać IOError dekompresji?

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 

kompiluje dobrze, ale wydaje się, że to nie jest poprawny sposób obsłużyć pliki nieskompresowane. Uruchomienie kodu w pliku skompresowanym działa ładnie, ale nieskompresowany plik nie powiedzie się z wyjątkiem:

*** Exception: Codec.Compression.Zlib: incorrect header check 

Każdy pomysł na jak było to możliwe?

+0

'IO.try' jest przestarzała ... co z Control.Exception.try'? http://hackage.haskell.org/packages/archive/base/latest/doc/html/Control-Exception.html#v;try –

+2

Co ważniejsze, 'IO.try' szczególnie nie przechwytuje wyjątków od czystego kodu , podczas gdy 'Control.Exception.try' ma. – dave4420

Odpowiedz

4

Musisz zaimportować Codec.Compression.Zlib.Internal. Zwróć szczególną uwagę na sekcję zatytułowaną “Low-level API to get explicit error reports”.

Będziemy chcieli użyć czegoś takiego (nota niesprawdzone):

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 

(przypuszczam zaimportowaniu Data.ByteString.Lazy zakwalifikowane jako L.)

+0

wow ... czy mógłbyś wyjaśnić, co się tutaj dzieje? :) – fho

+0

Nieważne, czy to działa ?! (Które z tych bitów nie rozumiesz? "DecompressWithErrors" i "foldDecompressStream" itp. Są wyjaśnione (być może niewystarczająco jasno?) W dokumentacji, z którą się łączyłem.) – dave4420

+0

Skąd się bierze ta finalizująca metoda? Nie znalazłem tego przez hayoo. – fho

2

Być może zechcesz spojrzeć na numer spoon, który pozwoli Ci uzyskać Nothing, jeśli zgłoszony został wyjątek.