2013-11-21 7 views
5

タイトルによれば、zipアーカイブ内にあるファイルからzip-conduit(zipファイル私は扱っている非常に大きい、私は定数メモリでこれを行うことができる必要があります)。私は導管の基本的なアイデアを突き詰めましたが、怒りの中でそれらを使ったことは一度もなく、どこから始めるべきかについて非常に固執しています。私はコンジットチュートリアルを読んだことがありますが、私はそれを自分の問題と一致させるのに問題があります。Haskellのzip-conduitを使用してzipアーカイブ内のファイルから行を読み取る

ジップコンジットのドキュメントは1つが、以下のようなものを経由してzipアーカイブから供給することができます言う:私は何をする必要があるか推測

import qualified Data.Conduit.Binary as CB 
import Codec.Archive.Zip 

withArchive archivePath $ do 
    name:_ <- entryNames 
    sourceEntry name $ CB.sinkFile name 

CB.sinkFileの代わりに何かを書くです。 Data.Conduit.Textlinesの機能を持っています - ファイルの行を取得するためにこれを何らかの方法で使用できますか?

単純な例があります。たとえば、putStrLnを使用して、zipファイル内にアーカイブされた単純なテキストファイルの行を書き出すとします。前もって感謝します。

import   Control.Monad.IO.Class (liftIO) 
import   Data.Conduit 
import qualified Data.Conduit.Binary as CB 
import qualified Data.Conduit.List  as CL 
import qualified Data.Conduit.Text  as CT 

main :: IO() 
main = runResourceT 
    $ CB.sourceFile "input.txt" 
    $$ CT.decode CT.utf8 
    =$ CT.lines 
    =$ CL.mapM_ (\t -> liftIO $ putStrLn $ "Got a line: " ++ show t) 

することもできますview and experiment on FP Haskell Center

答えて

6

マイケルの答えが、zip-conduitと:、マイケルを返信する時間を割いて

import   Control.Monad.IO.Class (liftIO) 
import   Data.Conduit 
import qualified Data.Conduit.List as CL 
import qualified Data.Conduit.Text as CT 
import   Codec.Archive.Zip 

main :: IO() 
main = withArchive "input.zip" $ do 
    n:_ <- entryNames 
    sourceEntry n 
    $ CT.decode CT.utf8 
    =$ CT.lines 
    =$ CL.mapM_ (\t -> liftIO $ putStrLn $ "Got a line: " ++ show t) 
+0

ありがとう、これははるかに理にかなっています。コンジットを使用して私のコードをもっときれいにしました。 – Chris

1

は、ここで簡単な例を示します。ここで

+1

感謝。あなたの例は、私が導管チュートリアルから理解している導管の一般的な使用法を示していますが、私の質問に概説されているように、どのように蛇管を使用するのかを示していません。あなたの例からソリューションへさらに本当に助けになるでしょう! – Chris

+0

この例は機能しません:スコープ内に変数がありません:main :: [GHC.Types.Char] - > t " – Christophe

1

は、それがシンク機能(必要に応じてCL、CBの機能を使用して消費する)に伝わってくるよう、またはデータが遅延して返送されているので、あなたがデータを処理することができますいずれかの簡単な例 -

import Data.ByteString as B 
import Data.Conduit 
import qualified Data.Conduit.List as CL 
import qualified Data.Conduit.Binary as CB 
import Codec.Archive.Zip 
import System.Environment 

sink :: Monad m => Sink ByteString m [ByteString] 
sink = CL.consume 

main::IO() 
main = do 
    [archivePath] <- getArgs 
    res <- withArchive archivePath $ do 
     name:_ <- entryNames 
     source <- getSource name 
     runResourceT $ (source $$ sink) 

    print res 

です、resのデータを変更することができます。

+0

ありがとう、@jamshidh。しかし、私はシンク関数でどのように物事を正確に処理するでしょうか? 'res'を文字列のリストに変換して処理すると、このリストに含まれる要素の数がはるかに少ないことがわかります。アイテムの数は、必要なメモリによって制限されているように見えます。私は 'res'が怠惰であるとは確信していません(ドキュメンテーションは' CB.consume'がすべての値をメモリに入れていると言っています)。あなたの 'sink '関数を修正して、各行を些細に処理する(たとえば、各行に与えられた文字列を追加する)のはどうでしょうか? – Chris

関連する問題