diff --git a/seqloc-datafiles.cabal b/seqloc-datafiles.cabal
--- a/seqloc-datafiles.cabal
+++ b/seqloc-datafiles.cabal
@@ -1,5 +1,5 @@
 Name:                seqloc-datafiles
-Version:             0.2
+Version:             0.2.1
 Cabal-Version:       >= 1.4
 Synopsis:            Read and write BED and GTF format genome annotations
 Description:         Read and write BED and GTF format genome annotations
diff --git a/src/Bio/SeqLoc/Bed.hs b/src/Bio/SeqLoc/Bed.hs
--- a/src/Bio/SeqLoc/Bed.hs
+++ b/src/Bio/SeqLoc/Bed.hs
@@ -12,6 +12,7 @@
 import Control.Monad
 import qualified Data.ByteString.Char8 as BS
 import Data.List
+import Data.Maybe
 import Data.Ord
 
 import qualified Data.Attoparsec.Zepto as ZP
@@ -80,7 +81,7 @@
 -- | Minimalistic 'ZP.Parser'-style parser for a BED format line, not
 -- including the trailing newline.
 bedZP :: ZP.Parser Transcript
-bedZP = do chrom <- field -- The name of the chromosome
+bedZP = do chrom <- firstfield -- The name of the chromosome
            chromStart <- decfield -- The starting position of the
                                   -- feature in the chromosome or
                                   -- scaffold. The first base in a
@@ -94,31 +95,39 @@
                                 -- chromStart=0, chromEnd=100, and
                                 -- span the bases numbered 0-99.
            name <- field -- Defines the name of the BED line.
-           _score <- dropField -- A score between 0 and 1000.
-           str <- strand -- Defines the strand
-           thickStart <- decfield -- The starting position at which
+           _score <- unlessAtEnd dropField -- A score between 0 and 1000.
+           str <- fromMaybe Plus <$> unlessAtEnd strand -- Defines the strand
+           thickStart <- unlessAtEnd decfield -- The starting position at which
                                   -- the feature is drawn thickly (for
                                   -- example, the start codon in gene
                                   -- displays).
-           thickEnd <- decfield -- The ending position at which the
+           thickEnd <- unlessAtEnd decfield -- The ending position at which the
                                 -- feature is drawn thickly (for
                                 -- example, the stop codon in gene
                                 -- displays).
-           _itemRGB <- dropField -- An RGB value of the form R,G,B
-                                 -- (e.g. 255,0,0).
-           blockCount <- decfield -- The number of blocks (exons) in
+           _itemRGB <- unlessAtEnd dropField -- An RGB value of the form R,G,B
+                                             -- (e.g. 255,0,0).
+           blockCount <- unlessAtEnd decfield -- The number of blocks (exons) in
                                   -- the BED line.
-           blockSizes <- commas blockCount decimal <* dropField
-                         -- A comma-separated list of the block sizes.                         
-           blockStarts <- commas blockCount decimal 
-                          -- A comma-separated list of block starts.
-           loc <- bedTrxLoc chromStart chromEnd str $ zip blockSizes blockStarts
+           blockSizes <- case blockCount of
+             Just ct -> unlessAtEnd $ commas ct decimal
+                        -- A comma-separated list of the block sizes.                         
+             Nothing -> return Nothing
+           blockStarts <- case blockCount of
+             Just ct -> unlessAtEnd $ commas ct decimal 
+                        -- A comma-separated list of block starts.
+             Nothing -> return Nothing
+           loc <- case liftM2 zip blockSizes blockStarts of
+             Just blocks -> bedTrxLoc chromStart chromEnd str blocks
+             Nothing -> maybe badContig return $ 
+                        SpLoc.fromContigs [ Loc.fromBoundsStrand chromStart (chromEnd - 1) str ]
+                          where badContig = error "bedZP: Bad singleton sploc!"
            unless (Loc.bounds loc == (chromStart, chromEnd - 1)) $
              fail $ "Bio.SeqLoc.Bed: bad sploc:" ++ 
              (BS.unpack . BS.unwords $ [ repr loc, repr chromStart, repr chromEnd ])
-           cdsloc <- if thickStart >= thickEnd
-                        then return Nothing
-                        else liftM Just $! bedCdsLoc loc thickStart thickEnd
+           cdsloc <- case liftM2 (,) thickStart thickEnd of
+             Just (start, end) -> liftM Just $! bedCdsLoc loc start end
+             Nothing -> return Nothing
            let n = toSeqLabel $ BS.copy name
                c = toSeqLabel $ BS.copy chrom
            return $! Transcript n n (OnSeq c loc) cdsloc
@@ -140,5 +149,7 @@
 
 commas :: Int -> ZP.Parser a -> ZP.Parser [a]
 commas n p | n < 1     = return [] 
-           | otherwise = (:) <$> p <*>
-                         replicateM (n - 1) (ZP.string "," *> p)
+           | otherwise = ZP.string "\t" *> 
+                         ( (:) <$> p <*>
+                           replicateM (n - 1) (ZP.string "," *> p) )
+                         <* (ZP.string "," <|> return ())
diff --git a/src/Bio/SeqLoc/GTF.hs b/src/Bio/SeqLoc/GTF.hs
--- a/src/Bio/SeqLoc/GTF.hs
+++ b/src/Bio/SeqLoc/GTF.hs
@@ -182,7 +182,7 @@
 
 -- Does NOT consume the remainder of the line
 gtfline :: ZP.Parser GtfLine
-gtfline = do seqname <- field
+gtfline = do seqname <- firstfield
              _source <- dropField
              ftype <- field
              start <- decfield
diff --git a/src/Bio/SeqLoc/ZeptoUtils.hs b/src/Bio/SeqLoc/ZeptoUtils.hs
--- a/src/Bio/SeqLoc/ZeptoUtils.hs
+++ b/src/Bio/SeqLoc/ZeptoUtils.hs
@@ -13,20 +13,27 @@
 
 import Bio.SeqLoc.Strand
 
+firstfield :: ZP.Parser BS.ByteString
+firstfield = ZP.takeWhile (/= c2w '\t')
+
 strand :: ZP.Parser Strand
-strand = ((ZP.string "+\t" *> return Plus) <|>
-          (ZP.string "-\t" *> return Minus))
+strand = ((ZP.string "\t+" *> return Plus) <|>
+          (ZP.string "\t-" *> return Minus))
 
 decfield :: (Integral a) => ZP.Parser a
-decfield = decimal <* ZP.string "\t"
+decfield = ZP.string "\t" *> decimal
 
 field :: ZP.Parser BS.ByteString
-field =  ZP.takeWhile (/= c2w '\t') <* ZP.string "\t"
+field =  ZP.string "\t" *> ZP.takeWhile (/= c2w '\t')
 
 dropField :: ZP.Parser ()
-dropField = ZP.takeWhile (/= c2w '\t') *> ZP.string "\t" *> return ()
+dropField = ZP.string "\t" *> ZP.takeWhile (/= c2w '\t') *> return ()
 
 decimal :: (Integral a) => ZP.Parser a
 decimal = decode <$> ZP.takeWhile (AP.isDigit_w8)
   where decode = fromIntegral . BSW.foldl' step (0 :: Int)
         step a w = a * 10 + fromIntegral (w - 48)
+
+unlessAtEnd :: ZP.Parser a -> ZP.Parser (Maybe a)
+unlessAtEnd p = do isAtEnd <- ZP.atEnd
+                   if isAtEnd then return Nothing else fmap Just p
