diff --git a/Data/ByteString/Streaming.hs b/Data/ByteString/Streaming.hs
--- a/Data/ByteString/Streaming.hs
+++ b/Data/ByteString/Streaming.hs
@@ -109,6 +109,13 @@
     
     , concat          -- concat :: Monad m => Stream (ByteString m) m r -> ByteString m r 
 
+    -- * Builders
+    
+    , toStreamingByteStringWith
+    , toStreamingByteString
+    , toBuilder
+    , concatBuilders
+    
     -- * Building ByteStrings
     
     -- ** Infinite ByteStrings
@@ -177,14 +184,16 @@
 import qualified Data.ByteString        as S  -- S for strict (hmm...)
 import qualified Data.ByteString.Internal as S
 import qualified Data.ByteString.Unsafe as S
+import Data.ByteString.Builder.Internal hiding (hPut, defaultChunkSize, empty, append)
 
 import Data.ByteString.Streaming.Internal 
 import Streaming hiding (concats, unfold, distribute, wrap)
 import Streaming.Internal (Stream (..))
 import qualified Streaming.Prelude as SP
 
-import Control.Monad            (liftM, forever)
 
+import Control.Monad            (liftM, forever)
+import Data.Monoid              (Monoid(..))
 import Data.Word                (Word8)
 import Data.Int                 (Int64)
 import System.IO                (Handle,openBinaryFile,IOMode(..)
@@ -1554,3 +1563,74 @@
          case e of 
            Left stream -> loop stream
            Right (bs, qbs) -> Step (chunk bs >> fmap loop qbs)
+           
+{- Take a builder constructed otherwise and convert it to a genuine
+   streaming bytestring.  
+           
+>>>  Q.putStrLn $ Q.toStreamingByteString $ stringUtf8 "哈斯克尔" <> stringUtf8 " " <> integerDec 98
+哈斯克尔 98
+           
+    <https://gist.github.com/michaelt/6ea89ca95a77b0ef91f3 This benchmark> shows its
+    indistinguishable performance is indistinguishable from @toLazyByteString@
+
+           
+-}
+
+toStreamingByteString
+  :: MonadIO m => Builder -> ByteString m ()
+toStreamingByteString = toStreamingByteStringWith
+ (safeStrategy BI.smallChunkSize BI.defaultChunkSize)
+{-#INLINE toStreamingByteString #-}
+{-#SPECIALIZE toStreamingByteString :: Builder -> ByteString IO () #-}
+
+{-| Take a builder and convert it to a genuine
+   streaming bytestring, using a specific allocation strategy.
+-}
+toStreamingByteStringWith
+   :: MonadIO m =>
+      AllocationStrategy -> Builder -> ByteString m ()
+toStreamingByteStringWith strategy builder0 = do
+       cios <- liftIO (buildStepToCIOS strategy (runBuilder builder0))
+       let loop cios0 = case cios0 of
+              Yield1 bs io   -> Chunk bs $ do 
+                    cios1 <- liftIO io 
+                    loop cios1 
+              Finished buf r -> trimmedChunkFromBuffer buf (Empty r)
+           trimmedChunkFromBuffer buffer k 
+              | S.null bs                            = k
+              |  2 * S.length bs < bufferSize buffer = Chunk (S.copy bs) k
+              | otherwise                            = Chunk bs          k
+              where
+                bs = byteStringFromBuffer buffer
+       loop cios
+{-#INLINABLE toStreamingByteStringWith #-}
+{-#SPECIALIZE toStreamingByteStringWith ::  AllocationStrategy -> Builder -> ByteString IO () #-}
+           
+           
+{- Concatenate a stream of builders (not a streaming bytestring!) into a single builder.
+
+>>> let aa = yield (integerDec 10000) >> yield (string8 " is a number.") >> yield (char8 '\n')
+>>>  hPutBuilder  IO.stdout $ concatBuilders aa
+10000 is a number.
+
+-}
+concatBuilders :: Stream (Of Builder) IO () -> Builder
+concatBuilders p = builder $ \bstep r -> do 
+  case p of
+    Return _          -> runBuilderWith mempty bstep r
+    Step (b :> rest)  -> runBuilderWith (b `mappend` concatBuilders rest) bstep r 
+    Delay m            -> m >>= \p' -> runBuilderWith (concatBuilders p') bstep r
+{-#INLINABLE concatBuilders #-}
+
+
+{-| A simple construction of a builder from a byte stream.
+
+>>> let aaa = "10000 is a number\n" :: Q.ByteString IO ()
+>>>  hPutBuilder  IO.stdout $ toBuilder  aaa
+10000 is a number
+
+
+-}
+toBuilder :: ByteString IO () -> Builder
+toBuilder  =  concatBuilders . SP.map byteString . toChunks
+{-#INLINABLE toBuilder #-}
diff --git a/Data/ByteString/Streaming/Char8.hs b/Data/ByteString/Streaming/Char8.hs
--- a/Data/ByteString/Streaming/Char8.hs
+++ b/Data/ByteString/Streaming/Char8.hs
@@ -82,6 +82,13 @@
 
     , concat          -- concat :: Monad m => Stream (ByteString m) m r -> ByteString m r 
 
+    -- * Builders
+    
+    , toStreamingByteString
+    , toStreamingByteStringWith
+    , toBuilder
+    , concatBuilders
+    
     -- * Building ByteStrings
 
     -- ** Infinite ByteStrings
@@ -159,7 +166,8 @@
 import Data.ByteString.Streaming
     (fromLazy, toLazy, toLazy', nextChunk, unconsChunk, 
     fromChunks, toChunks, fromStrict, toStrict, toStrict', 
-    concat, distribute, drain,
+    concat, distribute, drain, toStreamingByteStringWith,
+    toStreamingByteString, toBuilder, concatBuilders,
     empty, null, null', length, length', append, cycle, 
     take, drop, splitAt, intercalate, group, denull,
     appendFile, stdout, stdin, fromHandle, toHandle,
diff --git a/streaming-bytestring.cabal b/streaming-bytestring.cabal
--- a/streaming-bytestring.cabal
+++ b/streaming-bytestring.cabal
@@ -1,5 +1,5 @@
 name:                streaming-bytestring
-version:             0.1.0.3
+version:             0.1.0.4
 synopsis:            effectful byte steams, or: lazy bytestring done right
 description:         This is an implementation of effectful, memory-constrained 
                      bytestrings (byte streams) and functions for streaming 
@@ -33,12 +33,13 @@
                      .
                      > data ByteString     = Empty   | Chunk Strict.ByteString ByteString
                      .
-                     with the minimal effectful variant
+                     with the /minimal/ effectful variant:
                      .
                      > data ByteString m r = Empty r | Chunk Strict.ByteString (ByteString m r) | Go (m (ByteString m r))
                      .
                      (Constructors are necessarily hidden in internal modules in both cases.) 
-                     As a lazy bytestring is implemented internally 
+                     .
+                     That's it. As a lazy bytestring is implemented internally 
                      by a sort of list of strict bytestring chunks, a streaming bytestring is 
                      simply implemented as a /producer/ or /generator/ of strict bytestring chunks.
                      Most operations are defined by simply adding a line to what we find in
@@ -102,17 +103,17 @@
                      this library depends the @streaming@ library, which is used in place 
                      of @free@ to express the (streaming) splitting and division of byte streams. 
                      Those elementary concepts are catastrophically mishandled in the streaming io libraries 
-                     other than pipes; already the @enumerator@ and @iteratee@ libraries
-                     were completely defeated by it: see e.g. the implementation of 
+                     other than pipes. Already the @enumerator@ and @iteratee@ libraries
+                     were completely defeated by it: see e.g. the @enumerator@ implementation of 
                      <http://hackage.haskell.org/package/enumerator-0.4.20/docs/Data-Enumerator-Text.html#v:splitWhen splitWhen and lines>.
                      This will concatenate strict text forever, if that's what is coming
-                     in.
+                     in.  It becomes torture to express elementary distinctions. 
                      .
                      Though we barely alter signatures in @Data.ByteString.Lazy@ 
-                     more than is required
-                     by the types, the point of view that emerges is very much that of
+                     more than is required  by the types, 
+                     the point of view that emerges is very much that of
                      @pipes-bytestring@ and @pipes-group@. In particular
-                     we have the correspondences:
+                     we have these correspondences:
                      .
                      > Lazy.splitAt      :: Int -> ByteString              -> (ByteString, ByteString)
                      > Streaming.splitAt :: Int -> ByteString m r          -> ByteString m (ByteString m r)
@@ -163,4 +164,4 @@
 
   -- hs-source-dirs:      
   default-language:    Haskell2010
-  -- ghc-options: -Wall
+  ghc-options: -O2
