diff --git a/CHANGELOG b/CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,7 @@
 ------------
   * bugfixes for #if defined(FOO) && FOO(a,b)
   * (1.20.1): fix version number
+  * (1.20.2): ensure all input/output is UTF8, regardless of locale
 
 Version 1.19
 ------------
diff --git a/Language/Preprocessor/Cpphs/ReadFirst.hs b/Language/Preprocessor/Cpphs/ReadFirst.hs
--- a/Language/Preprocessor/Cpphs/ReadFirst.hs
+++ b/Language/Preprocessor/Cpphs/ReadFirst.hs
@@ -13,12 +13,15 @@
 
 module Language.Preprocessor.Cpphs.ReadFirst
   ( readFirst
+  , readFileUTF8
+  , writeFileUTF8
   ) where
 
-import System.IO        (hPutStrLn, stderr)
+import System.IO
 import System.Directory (doesFileExist)
-import Data.List      (intersperse)
-import Control.Monad     (when)
+import Data.List        (intersperse)
+import Control.Exception as E
+import Control.Monad    (when)
 import Language.Preprocessor.Cpphs.Position  (Posn,directory,cleanPath)
 
 -- | Attempt to read the given file from any location within the search path.
@@ -51,5 +54,20 @@
         let file = cleanPath p++'/':cleanPath name
         ok <- doesFileExist file
         if not ok then try name ps
-          else do content <- readFile file
+          else do content <- readFileUTF8 file
                   return (file,content)
+
+readFileUTF8 :: FilePath -> IO String
+readFileUTF8 file = do
+    h <- openFile file ReadMode
+    (do utf8r <- mkTextEncoding "UTF-8//ROUNDTRIP"
+        hSetEncoding h utf8r
+        hGetContents h) `E.onException` (hClose h)
+
+writeFileUTF8 :: FilePath -> String -> IO ()
+writeFileUTF8 f txt = withFile f WriteMode $ \hdl->
+                          do utf8r <- mkTextEncoding "UTF-8//ROUNDTRIP"
+                             hSetEncoding hdl utf8r
+                             hPutStr hdl txt
+                          `E.onException` (hClose hdl)
+
diff --git a/cpphs.cabal b/cpphs.cabal
--- a/cpphs.cabal
+++ b/cpphs.cabal
@@ -1,5 +1,5 @@
 Name: cpphs
-Version: 1.20.1
+Version: 1.20.2
 Copyright: 2004-2016, Malcolm Wallace
 License: LGPL
 License-File: LICENCE-LGPL
@@ -7,6 +7,7 @@
 Author: Malcolm Wallace <Malcolm.Wallace@me.com>
 Maintainer: Malcolm Wallace <Malcolm.Wallace@me.com>
 Homepage: http://projects.haskell.org/cpphs/
+bug-reports: https://github.com/malcolmwallace/cpphs/issues
 Synopsis: A liberalised re-implementation of cpp, the C pre-processor.
 Description:
     Cpphs is a re-implementation of the C pre-processor that is both
diff --git a/cpphs.hs b/cpphs.hs
--- a/cpphs.hs
+++ b/cpphs.hs
@@ -15,15 +15,20 @@
 import System.Exit ( exitWith, ExitCode(..) )
 import Data.Maybe
 import Language.Preprocessor.Cpphs ( runCpphs, CpphsOptions(..), parseOptions )
-import System.IO     ( stdout, IOMode(WriteMode), openFile, hPutStr, hFlush, hClose )
+import Language.Preprocessor.Cpphs.ReadFirst ( readFileUTF8, writeFileUTF8 )
+import System.IO     ( stdin, stdout, stderr, hFlush, hSetEncoding, utf8 )
 import Control.Monad  ( when )
 import Data.List   ( isPrefixOf )
 
 version :: String
-version = "1.20.1"
+version = "1.20.2"
 
 main :: IO ()
 main = do
+  hSetEncoding stdin  utf8
+  hSetEncoding stdout utf8
+  hSetEncoding stderr utf8
+
   args <- getArgs
   args <- return $ if "--cpp" `elem` args then convertArgs args else args
   
@@ -60,10 +65,10 @@
 execute :: CpphsOptions -> Maybe FilePath -> Maybe FilePath -> IO ()
 execute opts ofile infile =
   let (filename, readIt) = case infile of
-                             Just x  -> (x,       readFile x)
+                             Just x  -> (x,       readFileUTF8 x)
                              Nothing -> ("stdin", getContents)
       output Nothing x  = do putStr x; hFlush stdout
-      output (Just f) x = writeFile f x
+      output (Just f) x = writeFileUTF8 f x
   in do contents <- readIt
         transformed <- runCpphs opts filename contents
         output ofile transformed
diff --git a/docs/index.html b/docs/index.html
--- a/docs/index.html
+++ b/docs/index.html
@@ -198,12 +198,11 @@
 <b>Current stable version:</b>
 
 <p>
-cpphs-1.20, release date 2016-03-04<br>
+cpphs-1.20.2, release date 2016-09-05<br>
 By HTTP:
 <a href="http://hackage.haskell.org/package/cpphs">Hackage</a>.
 <ul>
-<li> bugfix for #if defined(FOO) &amp;&amp; FOO(a,b)
-<li> (1.20.1) fix version number
+<li> (1.20.2) ensure all input/output is UTF8, regardless of locale
 </ul>
 
 <p>
@@ -225,6 +224,16 @@
 
 <p>
 <b>Older versions:</b>
+
+<p>
+cpphs-1.20, release date 2016-03-04<br>
+By HTTP:
+<a href="http://hackage.haskell.org/package/cpphs">Hackage</a>.
+<ul>
+<li> bugfix for #if defined(FOO) &amp;&amp; FOO(a,b)
+<li> (1.20.1) fix version number
+<li> (1.20.2) ensure all input/output is UTF8, regardless of locale
+</ul>
 
 <p>
 cpphs-1.19.3, release date 2015-08-23<br>
