HaskellLazyIOを貸し出しています。
コピーの進行状況をコンソールに印刷しながら、大きなファイル(8Gb)をコピーするエレガントな方法を探しています。
ファイルをサイレントにコピーする次の簡単なプログラムについて考えてみます。
module Main where
import System
import qualified Data.ByteString.Lazy as B
main = do [from, to] <- getArgs
body <- B.readFile from
B.writeFile to body
レポートに使用するコールバック関数があると想像してください。
onReadBytes :: Integer -> IO ()
onReadBytes count = putStrLn $ "Bytes read: " ++ (show count)
質問: onReadBytes関数をLazy ByteStringに織り込んで、正常に読み取られたときにコールバックされるようにするにはどうすればよいですか?または、この設計が適切でない場合、Haskellの方法は何ですか?
注:コールバックの頻度は重要ではありません。1024バイトごとまたは1Mbごとに呼び出すことができます-重要ではありません
答え:答えてくれたcamccannに感謝します。完全に読むことをお勧めします。
Bellowは、camccannのコードに基づいた私のバージョンのコードです。便利な場合があります。
module Main where
import System
import System.IO
import qualified Data.ByteString.Lazy as B
main = do [from, to] <- getArgs
withFile from ReadMode $ \fromH ->
withFile to WriteMode $ \toH ->
copyH fromH toH $ \x -> putStrLn $ "Bytes copied: " ++ show x
copyH :: Handle -> Handle -> (Integer -> IO()) -> IO ()
copyH fromH toH onProgress =
copy (B.hGet fromH (256 * 1024)) (write toH) B.null onProgress
where write o x = do B.hPut o x
return . fromIntegral $ B.length x
copy :: (Monad m) => m a -> (a -> m Integer) -> (a -> Bool) -> (Integer -> m()) -> m()
copy = copy_ 0
copy_ :: (Monad m) => Integer -> m a -> (a -> m Integer) -> (a -> Bool) -> (Integer -> m()) -> m()
copy_ count inp outp done onProgress = do x <- inp
unless (done x) $
do n <- outp x
onProgress (n + count)
copy_ (n + count) inp outp done onProgress