diff --git a/Data/Text.hs b/Data/Text.hs
--- a/Data/Text.hs
+++ b/Data/Text.hs
@@ -195,7 +195,7 @@
 
 import Prelude (Char, Bool(..), Int, Maybe(..), String,
                 Eq(..), Ord(..), Ordering(..), (++),
-                Read(..), Show(..),
+                Read(..),
                 (&&), (||), (+), (-), (.), ($), ($!), (>>),
                 not, return, otherwise, quot)
 #if defined(HAVE_DEEPSEQ)
@@ -211,17 +211,20 @@
 import Control.Monad.ST (ST)
 import qualified Data.Text.Array as A
 import qualified Data.List as L
+import Data.Binary (Binary(get, put))
 import Data.Monoid (Monoid(..))
 import Data.String (IsString(..))
 import qualified Data.Text.Internal.Fusion as S
 import qualified Data.Text.Internal.Fusion.Common as S
+import Data.Text.Encoding (decodeUtf8, encodeUtf8)
 import Data.Text.Internal.Fusion (stream, reverseStream, unstream)
 import Data.Text.Internal.Private (span_)
-import Data.Text.Internal (Text(..), empty, empty_, firstf, mul, safe, text)
+import Data.Text.Internal (Text(..), empty, firstf, mul, safe, text)
+import Data.Text.Show (singleton, unpack)
 import qualified Prelude as P
 import Data.Text.Unsafe (Iter(..), iter, iter_, lengthWord16, reverseIter,
                          reverseIter_, unsafeHead, unsafeTail)
-import Data.Text.Internal.Unsafe.Char (unsafeChr, unsafeWrite)
+import Data.Text.Internal.Unsafe.Char (unsafeChr)
 import qualified Data.Text.Internal.Functions as F
 import qualified Data.Text.Internal.Encoding.Utf16 as U16
 import Data.Text.Internal.Search (indices)
@@ -230,15 +233,9 @@
 import qualified Data.Text.Lazy as L
 import Data.Int (Int64)
 #endif
-#if __GLASGOW_HASKELL__ >= 702
-import qualified GHC.CString as GHC
-#else
-import qualified GHC.Base as GHC
-#endif
 #if __GLASGOW_HASKELL__ >= 708
 import qualified GHC.Exts as Exts
 #endif
-import GHC.Prim (Addr#)
 
 -- $strict
 --
@@ -324,9 +321,6 @@
 instance Ord Text where
     compare = compareText
 
-instance Show Text where
-    showsPrec p ps r = showsPrec p (unpack ps) r
-
 instance Read Text where
     readsPrec p str = [(pack x,y) | (x,y) <- readsPrec p str]
 
@@ -349,6 +343,10 @@
 instance NFData Text where rnf !_ = ()
 #endif
 
+instance Binary Text where
+    put t = put (encodeUtf8 t)
+    get   = P.fmap decodeUtf8 get
+
 -- | This instance preserves data abstraction at the cost of inefficiency.
 -- We omit reflection services for the sake of data abstraction.
 --
@@ -400,54 +398,6 @@
 pack :: String -> Text
 pack = unstream . S.map safe . S.streamList
 {-# INLINE [1] pack #-}
-
--- | /O(n)/ Convert a 'Text' into a 'String'.  Subject to fusion.
-unpack :: Text -> String
-unpack = S.unstreamList . stream
-{-# INLINE [1] unpack #-}
-
--- | /O(n)/ Convert a literal string into a Text.  Subject to fusion.
-unpackCString# :: Addr# -> Text
-unpackCString# addr# = unstream (S.streamCString# addr#)
-{-# NOINLINE unpackCString# #-}
-
-{-# RULES "TEXT literal" forall a.
-    unstream (S.map safe (S.streamList (GHC.unpackCString# a)))
-      = unpackCString# a #-}
-
-{-# RULES "TEXT literal UTF8" forall a.
-    unstream (S.map safe (S.streamList (GHC.unpackCStringUtf8# a)))
-      = unpackCString# a #-}
-
-{-# RULES "TEXT empty literal"
-    unstream (S.map safe (S.streamList []))
-      = empty_ #-}
-
-{-# RULES "TEXT singleton literal" forall a.
-    unstream (S.map safe (S.streamList [a]))
-      = singleton_ a #-}
-
--- | /O(1)/ Convert a character into a Text.  Subject to fusion.
--- Performs replacement on invalid scalar values.
-singleton :: Char -> Text
-singleton = unstream . S.singleton . safe
-{-# INLINE [1] singleton #-}
-
-{-# RULES "TEXT singleton" forall a.
-    unstream (S.singleton (safe a))
-      = singleton_ a #-}
-
--- This is intended to reduce inlining bloat.
-singleton_ :: Char -> Text
-singleton_ c = Text (A.run x) 0 len
-  where x :: ST s (A.MArray s)
-        x = do arr <- A.new len
-               _ <- unsafeWrite arr 0 d
-               return arr
-        len | d < '\x10000' = 1
-            | otherwise     = 2
-        d = safe c
-{-# NOINLINE singleton_ #-}
 
 -- -----------------------------------------------------------------------------
 -- * Basic functions
diff --git a/Data/Text/Encoding.hs b/Data/Text/Encoding.hs
--- a/Data/Text/Encoding.hs
+++ b/Data/Text/Encoding.hs
@@ -84,12 +84,12 @@
 import Control.Monad.ST (runST)
 import Data.ByteString as B
 import Data.ByteString.Internal as B hiding (c2w)
-import Data.Text ()
 import Data.Text.Encoding.Error (OnDecodeError, UnicodeException, strictDecode)
 import Data.Text.Internal (Text(..), safe, text)
 import Data.Text.Internal.Private (runText)
 import Data.Text.Internal.Unsafe.Char (unsafeWrite)
 import Data.Text.Internal.Unsafe.Shift (shiftR)
+import Data.Text.Show ()
 import Data.Text.Unsafe (unsafeDupablePerformIO)
 import Data.Word (Word8, Word32)
 import Foreign.C.Types (CSize(..))
diff --git a/Data/Text/Lazy.hs b/Data/Text/Lazy.hs
--- a/Data/Text/Lazy.hs
+++ b/Data/Text/Lazy.hs
@@ -212,6 +212,7 @@
 import Data.Char (isSpace)
 import Data.Data (Data(gfoldl, toConstr, gunfold, dataTypeOf), constrIndex,
                   Constr, mkConstr, DataType, mkDataType, Fixity(Prefix))
+import Data.Binary (Binary(get, put))
 import Data.Monoid (Monoid(..))
 import Data.String (IsString(..))
 import qualified Data.Text as T
@@ -224,6 +225,7 @@
 import Data.Text.Internal.Lazy (Text(..), chunk, empty, foldlChunks,
                                 foldrChunks, smallChunkSize)
 import Data.Text.Internal (firstf, safe, text)
+import Data.Text.Lazy.Encoding (decodeUtf8, encodeUtf8)
 import qualified Data.Text.Internal.Functions as F
 import Data.Text.Internal.Lazy.Search (indices)
 #if __GLASGOW_HASKELL__ >= 702
@@ -353,6 +355,10 @@
     rnf (Chunk _ ts) = rnf ts
 #endif
 
+instance Binary Text where
+    put t = put (encodeUtf8 t)
+    get   = P.fmap decodeUtf8 get
+
 -- | This instance preserves data abstraction at the cost of inefficiency.
 -- We omit reflection services for the sake of data abstraction.
 --
@@ -961,7 +967,7 @@
 
 -- | @'iterate' f x@ returns an infinite 'Text' of repeated applications
 -- of @f@ to @x@:
--- 
+--
 -- > iterate f x == [x, f x, f (f x), ...]
 iterate :: (Char -> Char) -> Char -> Text
 iterate f c = let t c' = Chunk (T.singleton c') (t (f c'))
diff --git a/Data/Text/Lazy/Encoding.hs b/Data/Text/Lazy/Encoding.hs
--- a/Data/Text/Lazy/Encoding.hs
+++ b/Data/Text/Lazy/Encoding.hs
@@ -66,10 +66,9 @@
 import qualified Data.ByteString.Builder as B
 import qualified Data.ByteString.Builder.Extra as B (safeStrategy, toLazyByteStringWith)
 import qualified Data.ByteString.Builder.Prim as BP
-import qualified Data.Text as T
 #endif
+import qualified Data.Text as T
 import qualified Data.Text.Encoding as TE
-import qualified Data.Text.Lazy as L
 import qualified Data.Text.Internal.Lazy.Encoding.Fusion as E
 import qualified Data.Text.Internal.Lazy.Fusion as F
 import Data.Text.Unsafe (unsafeDupablePerformIO)
@@ -110,7 +109,7 @@
       | S.null l  = empty
       | otherwise = case onErr desc (Just (B.unsafeHead l)) of
                       Nothing -> empty
-                      Just c  -> L.singleton c
+                      Just c  -> Chunk (T.singleton c) Empty
     desc = "Data.Text.Lazy.Encoding.decodeUtf8With: Invalid UTF-8 stream"
 decodeUtf8With _ _ = empty
 
diff --git a/Data/Text/Show.hs b/Data/Text/Show.hs
new file mode 100644
--- /dev/null
+++ b/Data/Text/Show.hs
@@ -0,0 +1,85 @@
+{-# LANGUAGE CPP, MagicHash #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+#if __GLASGOW_HASKELL__ >= 702
+{-# LANGUAGE Trustworthy #-}
+#endif
+
+-- |
+-- Module      : Data.Text.Show
+-- Copyright   : (c) 2009-2015 Bryan O'Sullivan
+--
+-- License     : BSD-style
+-- Maintainer  : bos@serpentine.com
+-- Stability   : experimental
+-- Portability : GHC
+
+module Data.Text.Show
+    (
+      singleton
+    , unpack
+    ) where
+
+import Control.Monad.ST (ST)
+import Data.Text.Internal (Text(..), empty_, safe)
+import Data.Text.Internal.Fusion (stream, unstream)
+import Data.Text.Internal.Unsafe.Char (unsafeWrite)
+import GHC.Prim (Addr#)
+import qualified Data.Text.Array as A
+import qualified Data.Text.Internal.Fusion.Common as S
+
+#if __GLASGOW_HASKELL__ >= 702
+import qualified GHC.CString as GHC
+#else
+import qualified GHC.Base as GHC
+#endif
+
+instance Show Text where
+    showsPrec p ps r = showsPrec p (unpack ps) r
+
+-- | /O(n)/ Convert a 'Text' into a 'String'.  Subject to fusion.
+unpack :: Text -> String
+unpack = S.unstreamList . stream
+{-# INLINE [1] unpack #-}
+
+-- | /O(n)/ Convert a literal string into a Text.  Subject to fusion.
+unpackCString# :: Addr# -> Text
+unpackCString# addr# = unstream (S.streamCString# addr#)
+{-# NOINLINE unpackCString# #-}
+
+{-# RULES "TEXT literal" forall a.
+    unstream (S.map safe (S.streamList (GHC.unpackCString# a)))
+      = unpackCString# a #-}
+
+{-# RULES "TEXT literal UTF8" forall a.
+    unstream (S.map safe (S.streamList (GHC.unpackCStringUtf8# a)))
+      = unpackCString# a #-}
+
+{-# RULES "TEXT empty literal"
+    unstream (S.map safe (S.streamList []))
+      = empty_ #-}
+
+{-# RULES "TEXT singleton literal" forall a.
+    unstream (S.map safe (S.streamList [a]))
+      = singleton_ a #-}
+
+-- | /O(1)/ Convert a character into a Text.  Subject to fusion.
+-- Performs replacement on invalid scalar values.
+singleton :: Char -> Text
+singleton = unstream . S.singleton . safe
+{-# INLINE [1] singleton #-}
+
+{-# RULES "TEXT singleton" forall a.
+    unstream (S.singleton (safe a))
+      = singleton_ a #-}
+
+-- This is intended to reduce inlining bloat.
+singleton_ :: Char -> Text
+singleton_ c = Text (A.run x) 0 len
+  where x :: ST s (A.MArray s)
+        x = do arr <- A.new len
+               _ <- unsafeWrite arr 0 d
+               return arr
+        len | d < '\x10000' = 1
+            | otherwise     = 2
+        d = safe c
+{-# NOINLINE singleton_ #-}
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,13 @@
+1.2.1.0
+
+* Added Binary instances for both Text types. (If you have previously
+  been using the text-binary package to get a Binary instance, it is
+  now obsolete.)
+
+1.2.0.6
+
+* Fixed a space leak in UTF-8 decoding
+
 1.2.0.5
 
 * Feature parity: repeat, cycle, iterate are now implemented for lazy
diff --git a/tests/text-tests.cabal b/tests/text-tests.cabal
--- a/tests/text-tests.cabal
+++ b/tests/text-tests.cabal
@@ -114,6 +114,7 @@
     Data.Text.Internal.Lazy.Search
     Data.Text.Internal.Private
     Data.Text.Read
+    Data.Text.Show
     Data.Text.Internal.Read
     Data.Text.Internal.Search
     Data.Text.Unsafe
@@ -135,6 +136,7 @@
   build-depends:
     array,
     base == 4.*,
+    binary,
     bytestring,
     deepseq,
     ghc-prim,
diff --git a/text.cabal b/text.cabal
--- a/text.cabal
+++ b/text.cabal
@@ -1,5 +1,5 @@
 name:           text
-version:        1.2.0.6
+version:        1.2.1.0
 homepage:       https://github.com/bos/text
 bug-reports:    https://github.com/bos/text/issues
 synopsis:       An efficient packed Unicode text type.
@@ -121,9 +121,13 @@
     Data.Text.Read
     Data.Text.Unsafe
 
+  other-modules:
+    Data.Text.Show
+
   build-depends:
     array      >= 0.3,
     base       >= 4.2 && < 5,
+    binary,
     deepseq    >= 1.1.0.0,
     ghc-prim   >= 0.2
 
@@ -136,6 +140,7 @@
   ghc-options: -Wall -fwarn-tabs -funbox-strict-fields -O2
   if flag(developer)
     ghc-prof-options: -auto-all
+    ghc-options: -Werror
     cpp-options: -DASSERTS
 
   if flag(integer-simple)
@@ -163,6 +168,7 @@
     QuickCheck >= 2.7,
     array,
     base,
+    binary,
     bytestring,
     deepseq,
     directory,
