on 26354ba help sign in
streamly/examples/HandleIO.hs
107 lines 3.9 kB history raw
1import Data.Char (ord)
2import System.Environment (getArgs)
3import System.IO (IOMode(..), hSeek, SeekMode(..))
5import qualified Streamly.Data.Fold as FL
6import qualified Streamly.FileSystem.Handle as FH
7import qualified System.IO as FH
8import qualified Streamly.Memory.Array as A
9import qualified Streamly.Prelude as S
10-- import qualified Streamly.FileSystem.FD as FH
12import qualified Streamly.Internal.Data.Fold as FL
13import qualified Streamly.Internal.Data.Unicode.Stream as US
14import qualified Streamly.Internal.Memory.ArrayStream as AS
15import qualified Streamly.Internal.Prelude as S
17-- Read the contents of a file to stdout.
18--
19-- FH.read reads the file in 32KB chunks and converts the chunks into a byte
20-- stream. FH.write takes the byte stream as input, converts it into chunks of
21-- 32KB and writes those chunks to stdout.
22--
23_cat :: FH.Handle -> IO ()
24_cat src = S.fold (FH.write FH.stdout) $ S.unfold FH.read src
26-- Chunked version, more efficient than the byte stream version above. Reads
27-- the file in 256KB chunks and writes those chunks to stdout.
28cat :: FH.Handle -> IO ()
29cat src =
30 S.fold (FH.writeChunks FH.stdout)
31 $ S.unfold FH.readChunksWithBufferOf ((256*1024), src)
33-- Copy a source file to a destination file.
34--
35-- FH.read reads the file in 32KB chunks and converts the chunks into a byte
36-- stream. FH.write takes the byte stream as input, converts it into chunks of
37-- 32KB and writes those chunks to the destination file.
38_cp :: FH.Handle -> FH.Handle -> IO ()
39_cp src dst = S.fold (FH.write dst) $ S.unfold FH.read src
41-- Chunked version, more efficient than the byte stream version above. Reads
42-- the file in 256KB chunks and writes those chunks to stdout.
43cp :: FH.Handle -> FH.Handle -> IO ()
44cp src dst =
45 S.fold (FH.writeChunks dst)
46 $ S.unfold FH.readChunksWithBufferOf ((256*1024), src)
48ord' :: Num a => Char -> a
49ord' = (fromIntegral . ord)
51-- Count lines like wc -l.
52--
53-- Char stream version. Reads the input as a byte stream, splits it into lines
54-- and counts the lines..
55_wcl :: FH.Handle -> IO ()
56_wcl src = print =<< (S.length
57 $ US.lines FL.drain
58 $ US.decodeLatin1
59 $ S.unfold FH.read src)
61-- More efficient chunked version. Reads chunks from the input handles and
62-- splits the chunks directly instead of converting them into byte stream
63-- first.
64wcl :: FH.Handle -> IO ()
65wcl src = print =<< (S.length
66 $ AS.splitOn 10
67 $ S.unfold FH.readChunks src)
69-- grep -c
70--
71-- count the occurrences of a pattern in a file.
72grepc :: String -> FH.Handle -> IO ()
73grepc pat src = print . (subtract 1) =<< (S.length
74 $ S.splitOnSeq (A.fromList (map ord' pat)) FL.drain
75 $ S.unfold FH.read src)
77-- Compute the average line length in a file.
78avgll :: FH.Handle -> IO ()
79avgll src = print =<< (S.fold avg
80 $ S.splitWithSuffix (== ord' '\n') FL.length
81 $ S.unfold FH.read src)
82 where avg = (/) <$> toDouble FL.sum <*> toDouble FL.length
83 toDouble = fmap (fromIntegral :: Int -> Double)
85-- histogram of line lengths in a file
86llhisto :: FH.Handle -> IO ()
87llhisto src = print =<< (S.fold (FL.classify FL.length)
88 $ S.map bucket
89 $ S.splitWithSuffix (== ord' '\n') FL.length
90 $ S.unfold FH.read src)
91 where
92 bucket n = let i = n `mod` 10 in if i > 9 then (9,n) else (i,n)
94main :: IO ()
95main = do
96 name <- fmap head getArgs
97 src <- FH.openFile name ReadMode
98 let rewind = hSeek src AbsoluteSeek 0
100 rewind >> putStrLn "cat" >> cat src -- Unix cat program
101 rewind >> putStr "wcl " >> wcl src -- Unix wc -l program
102 rewind >> putStr "grepc " >> grepc "aaaa" src -- Unix grep -c program
103 rewind >> putStr "avgll " >> avgll src -- get average line length
104 rewind >> putStr "llhisto " >> llhisto src -- get line length histogram
106 dst <- FH.openFile "dst-xyz.txt" WriteMode
107 rewind >> putStr "cp " >> cp src dst -- Unix cp program