   [rdr finish]
   (when (and (not (zero? (.available (.reader rdr))))
              (> finish (.getFilePointer (.reader rdr))))
-    (cons (read-alignment (.reader rdr) (.refs rdr))
+    (cons (read-alignment (DataInputStream. (.reader rdr)) (.refs rdr))
           (lazy-seq (read-to-finish rdr finish)))))
 
+(defn- read-all
+  ([r refs offset length] (read-all r refs offset (+ offset length) 0 []))
+  ([^BamReader r ^clojure.lang.PersistentArrayMap refs
+    ^Integer start ^Integer end ^Integer n
+    ^clojure.lang.PersistentArrayMap alignments]
+     (if (>= n end)
+       alignments
+       (let [a (read-alignment r refs)
+             new-alignments (if (and (<= start n) (< n end))
+                              (conj alignments a)
+                              alignments)]
+         (recur r refs start end (inc n) new-alignments)))))
+
 (defn read-alignments
-  ([rdr]
-      (when-not (zero? (.available (.reader rdr)))
-        (cons (read-alignment (.reader rdr) (.refs rdr))
-              (lazy-seq (read-alignments rdr)))))
+  ([rdr offset length]
+     (let [r (.seq-reader rdr)
+           refs (.refs rdr)]
+       (when-not (zero? (.available (.reader rdr)))
+         (read-all r refs offset length))))
   ([rdr bai chr start end]
      (let [spans (get-spans bai chr start end)
            window (fn [a]


;;; I/O

(deftype BamReader [header refs reader]
  java.io.Closeable
  (close [this] (.. this reader close)))

(def ^:private buffer-size (* 1024 128))

(defn reader [f]
  (let [data-rdr (DataInputStream. (BlockCompressedInputStream. (file f)))
        rdr (DataInputStream.
             (BGZFInputStream.
              (BufferedInputStream. (FileInputStream. (file f)) buffer-size)))]
    (if-not (Arrays/equals (lsb/read-bytes rdr 4) (.getBytes bam-magic))
      (throw (IOException. "Invalid BAM file header")))
    (let [header (sam/parse-header (lsb/read-string rdr (lsb/read-int rdr)))
          n-ref  (lsb/read-int rdr)
          refs   (loop [i n-ref, ret []]
                   (if (zero? i)
                     ret
                     (let [l-name (lsb/read-int rdr)
                           name   (lsb/read-string rdr l-name)
                           l-ref  (lsb/read-int rdr)]
                       (recur (dec i)
                              (conj ret {:name (subs name 0 (dec l-name))
                                         :len  l-ref})))))]
      (->BamReader header refs rdr))))

(defn read-header
  [rdr]

  "Opens a reader on bam-file and reads all its headers and alignments,
  returning a map about sam records."
  [f & options]
  (let [{:keys [chr start end offset length] :or {chr nil
                                                  start 0
                                                  end -1
                                                  offset 0
                                                  length 0}} options]
    (with-open [r (reader f)]
      (let [header (read-header r)]
        (cond
         (not (nil? chr)) (with-open [i (bam-index f header)]
                            {:header header
                             :alignments (vec (read-alignments r i chr start end))})
         (pos? length) {:header header
                        :alignments (vec (read-alignments r offset length))})))))

(defn spit
  "Opposite of slurp-bam. Opens bam-file with writer, writes sam headers and
