diff --git a/Data/StorableVector.hs b/Data/StorableVector.hs
--- a/Data/StorableVector.hs
+++ b/Data/StorableVector.hs
@@ -155,6 +155,13 @@
         unzip,
         copy,
 
+        -- * IO
+        hGet,
+        hPut,
+        readFile,
+        writeFile,
+        appendFile,
+
   ) where
 
 import qualified Prelude as P
@@ -172,15 +179,19 @@
 
 import qualified Data.List as List
 
-import Control.Exception        (assert)
+import Control.Exception        (assert, bracket, )
 
 import Foreign.ForeignPtr
 import Foreign.Marshal.Array
 import Foreign.Ptr
 import Foreign.Storable         (Storable(..))
 
-import Data.Monoid              (Monoid, mempty, mappend, mconcat)
+import Data.Monoid              (Monoid, mempty, mappend, mconcat, )
 
+import System.IO                (openBinaryFile, hClose, hFileSize,
+                                 hGetBuf, hPutBuf,
+                                 Handle, IOMode(..), )
+
 #if !defined(__GLASGOW_HASKELL__)
 import System.IO.Unsafe
 #endif
@@ -1102,7 +1113,62 @@
 copy (SV x s l) = unsafeCreate l $ \p -> withForeignPtr x $ \f ->
     copyArray p (f `advancePtr` s) (fromIntegral l)
 
+
+
 -- ---------------------------------------------------------------------
+-- IO
+
+-- | Outputs a 'Vector' to the specified 'Handle'.
+hPut :: (Storable a) => Handle -> Vector a -> IO ()
+hPut h v =
+   if null v
+     then return ()
+     else
+       let (fptr, s, l) = toForeignPtr v
+       in  withForeignPtr fptr $ \ ptr ->
+              let ptrS = advancePtr ptr s
+                  ptrE = advancePtr ptrS l
+                  -- use advancePtr and minusPtr in order to respect alignment
+              in  hPutBuf h ptrS (minusPtr ptrE ptrS)
+
+-- | Read a 'Vector' directly from the specified 'Handle'.  This
+-- is far more efficient than reading the characters into a list
+-- and then using 'pack'.
+--
+hGet :: (Storable a) => Handle -> Int -> IO (Vector a)
+hGet _ 0 = return empty
+hGet h i =
+   createAndTrim i $ \p ->
+      let elemType :: Ptr a -> a
+          elemType _ = undefined
+          sizeOfElem = sizeOf (elemType p)
+      in  fmap (flip div sizeOfElem) $
+          hGetBuf h p (i * sizeOfElem)
+
+-- | Read an entire file strictly into a 'Vector'.  This is far more
+-- efficient than reading the characters into a 'String' and then using
+-- 'pack'.  It also may be more efficient than opening the file and
+-- reading it using hGet. Files are read using 'binary mode' on Windows.
+--
+readFile :: (Storable a) => FilePath -> IO (Vector a)
+readFile f =
+   bracket (openBinaryFile f ReadMode) hClose
+      (\h -> hGet h . fromIntegral =<< hFileSize h)
+
+-- | Write a 'Vector' to a file.
+writeFile :: (Storable a) => FilePath -> Vector a -> IO ()
+writeFile f txt =
+   bracket (openBinaryFile f WriteMode) hClose
+      (\h -> hPut h txt)
+
+-- | Append a 'Vector' to a file.
+appendFile :: (Storable a) => FilePath -> Vector a -> IO ()
+appendFile f txt =
+   bracket (openBinaryFile f AppendMode) hClose
+      (\h -> hPut h txt)
+
+
+-- ---------------------------------------------------------------------
 -- Internal utilities
 
 -- Common up near identical calls to `error' to reduce the number
@@ -1112,7 +1178,7 @@
 {-# NOINLINE errorEmptyList #-}
 
 moduleError :: String -> String -> a
-moduleError fun msg = error ("Data.Vector." ++ fun ++ ':':' ':msg)
+moduleError fun msg = error ("Data.StorableVector." ++ fun ++ ':':' ':msg)
 {-# NOINLINE moduleError #-}
 
 -- Find from the end of the string using predicate
diff --git a/storablevector.cabal b/storablevector.cabal
--- a/storablevector.cabal
+++ b/storablevector.cabal
@@ -1,5 +1,5 @@
 Name:                storablevector
-Version:             0.1.1
+Version:             0.1.2
 Category:            Data
 Synopsis:            Fast, packed, strict storable arrays with a list interface like ByteString
 Description:
diff --git a/tests/QuickCheckUtils.hs b/tests/QuickCheckUtils.hs
--- a/tests/QuickCheckUtils.hs
+++ b/tests/QuickCheckUtils.hs
@@ -17,7 +17,6 @@
 import Data.Int (Int64)
 import System.IO (hFlush, stdout, )
 
-import Data.ByteString.Fusion (PairS((:*:)), MaybeS(JustS, NothingS), )
 import qualified Data.ByteString      as P
 import qualified Data.StorableVector  as V
 import qualified Data.List as List
@@ -89,10 +88,6 @@
     arbitrary     = choose ('a', 'i')
     coarbitrary c = variant (ord c `rem` 4)
 
-instance (Arbitrary a, Arbitrary b) => Arbitrary (PairS a b) where
-  arbitrary             = liftM2 (:*:) arbitrary arbitrary
-  coarbitrary (a :*: b) = coarbitrary a . coarbitrary b
-
 instance Arbitrary Word8 where
     arbitrary = choose (97, 105)
     coarbitrary c = variant (fromIntegral ((fromIntegral c) `rem` 4))
@@ -100,11 +95,6 @@
 instance Arbitrary Int64 where
   arbitrary     = sized $ \n -> choose (-fromIntegral n,fromIntegral n)
   coarbitrary n = variant (fromIntegral (if n >= 0 then 2*n else 2*(-n) + 1))
-
-instance Arbitrary a => Arbitrary (MaybeS a) where
-  arbitrary            = do a <- arbitrary ; elements [NothingS, JustS a]
-  coarbitrary NothingS = variant 0
-  coarbitrary _        = variant 1 -- ok?
 
 {-
 instance Arbitrary Char where
