Haskell Lazy ByteString + 읽기 / 쓰기 진행 함수


0 Answers

Data.ByteString.Lazy.Progress를 사용하십시오. 데이터가 통과 할 때 모든 종류의 메트릭을 인쇄 할 수 있습니다.

Question

나는 Haskell Lazy IO를 사용하고있다.

나는 복사 진행을 콘솔로 출력하는 동안 큰 파일 (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 함수로 짜는 방법을 알려주므로 성공한 읽기에서 다시 호출 할 것인가? 또는이 디자인이 좋지 않다면, 하스켈은 그것을 어떻게 할 것입니까?

참고 : 콜백 빈도는 중요하지 않으며, 1,024 바이트마다 또는 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


Related