Online Book Reader

Home Category

Learn You a Haskell for Great Good! - Miran Lipovaca [89]

By Root 415 0
to examine a bytestring byte by byte, we need to unpack it. The unpack function is the inverse of pack. It takes a bytestring and turns it into a list of bytes.

Here’s an example:

ghci> let by = B.pack [98,111,114,116]

ghci> by

Chunk "bort" Empty

ghci> B.unpack by

[98,111,114,116]

You can also go back and forth between strict and lazy bytestrings. The toChunks function takes a lazy bytestring and converts it to a list of strict ones. The fromChunks function takes a list of strict bytestrings and converts it to a lazy bytestring:

ghci> B.fromChunks [S.pack [40,41,42], S.pack [43,44,45], S.pack [46,47,48]]

Chunk "()*" (Chunk "+,-" (Chunk "./0" Empty))

This is good if you have a lot of small strict bytestrings and you want to process them efficiently without joining them into one big strict bytestring in memory first.

The bytestring version of : is called cons. It takes a byte and a bytestring and puts the byte at the beginning.

ghci> B.cons 85 $ B.pack [80,81,82,84]

Chunk "U" (Chunk "PQRT" Empty)

The bytestring modules have a load of functions that are analogous to those in Data.List, including, but not limited to, head, tail, init, null, length, map, reverse, foldl, foldr, concat, takeWhile, filter, and so on. For a complete listing of bytestring functions, check out the documentation for the bytestring package at http://hackage.haskell.org/package/bytestring/.

The bytestring modules also have functions that have the same name and behave the same as some functions found in System.IO, but Strings are replaced with ByteStrings. For instance, the readFile function in System.IO has this type:

readFile :: FilePath -> IO String

The readFile function from the bytestring modules has the following type:

readFile :: FilePath -> IO ByteString

Note

If you’re using strict bytestrings and you attempt to read a file, all of that file will be read into memory at once! With lazy bytestrings, the file will be read in neat chunks.

Copying Files with Bytestrings


Let’s make a program that takes two filenames as command-line arguments and copies the first file into the second file. Note that System.Directory already has a function called copyFile, but we’re going to implement our own file-copying function and program anyway. Here’s the code:

import System.Environment

import System.Directory

import System.IO

import Control.Exception

import qualified Data.ByteString.Lazy as B

main = do

(fileName1:fileName2:_) <- getArgs

copy fileName1 fileName2

copy source dest = do

contents <- B.readFile source

bracketOnError

(openTempFile "." "temp")

(\(tempName, tempHandle) -> do

hClose tempHandle

removeFile tempName)

(\(tempName, tempHandle) -> do

B.hPutStr tempHandle contents

hClose tempHandle

renameFile tempName dest)

To begin, in main, we just get the command-line arguments and call our copy function, which is where the magic happens. One way to do this would be to just read from one file and write to another. But if something goes wrong (such as we don’t have enough disk space to copy the file), we’ll be left with a messed-up file. So we’ll write to a temporary file first. Then if something goes wrong, we can just delete that file.

First, we use B.readFile to read the contents of our source file. Then we use bracketOnError to set up our error handling. We acquire the resource with openTempFile "." "temp", which yields a tuple that consists of a temporary filename and a handle. Next, we say what we want to happen if an error occurs. If something goes wrong, we close the handle and remove the temporary file. Finally, we do the copying itself. We use B.hPutStr to write the contents to our temporary file. We close the temporary file and rename it to what we want it to be in the end.

Notice that we just used B.readFile and B.hPutStr instead of their regular variants. We didn’t need to use special bytestring functions for opening, closing, and renaming files. We just need to use the bytestring functions when reading and writing.

Let’s test it:

$ ./bytestringcopy bart.txt bort.txt

A program that doesn’t use

Return Main Page Previous Page Next Page

®Online Book Reader