Data.ByteString

GHC には、Data.ByteStringというモジュールがついています。バイナリファイルを扱うには、こいつを使った方がよさそうです。ファイル分割のプログラムを書き直してみました。

{-  Usage: splitfile path -}

module Main (main) where

import Prelude hiding (readFile, writeFile, take, drop, splitAt)
import Data.ByteString (ByteString, empty, readFile, writeFile, take, drop, splitAt)
import System (getArgs)

main :: IO ()
main = do args <- getArgs
          splitFile (head args)

blockSize = 100

splitFile :: FilePath -> IO ()
splitFile path = do content <- readFile path
                    putFiles $ zip (map (makeFileName) [1, 2 ..])
                                   (split blockSize content)
                 where
                    makeFileName :: Int -> String
                    makeFileName n = path ++ "." ++ (show n)

split :: Int -> ByteString -> [ByteString]
split n bytes
  | bytes == empty = []
  | otherwise      = let (f, rest) = splitAt n bytes
                     in  (f : split n rest)

putFiles :: [(FilePath, ByteString)] -> IO ()
putFiles [] = return ()
putFiles ((path, content):xs) = do writeFile path content
                                   putFiles xs


Stringと違って、ByteStringはリストではないので、リスト操作を行う関数が使えません。そのため、Data.ByteStringモジュールの中では、takeやdropなどの関数をあらためて定義しています。それ自体はいいのですが、単純にimportするとPreludeにある関数とバッティングするので、ちょっと扱いが面倒です。