diff --git a/log4hs.cabal b/log4hs.cabal
--- a/log4hs.cabal
+++ b/log4hs.cabal
@@ -4,10 +4,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 14d30e39d3ff2113f4ac08f122aa6f61a676b9d34facaafce1bc794bbeda7e10
+-- hash: a647fb460a908fafb35b6663c643cc259815b41a600dce95f217343328a72f6c
 
 name:           log4hs
-version:        0.0.7.0
+version:        0.1.0.0
 synopsis:       A python logging style log library
 description:    Please see the http://hackage.haskell.org/package/log4hs
 category:       logging
@@ -37,12 +37,14 @@
       Logging.Types.Filter
       Logging.Types.Formatter
       Logging.Types.Handlers
+      Logging.Types.Handlers.FileHandler
       Logging.Types.Handlers.StreamHandler
       Logging.Types.Level
       Logging.Types.Logger
       Logging.Types.Manager
       Logging.Types.Record
       Logging.Types.Sink
+      System.IO.Extra
       Paths_log4hs
   hs-source-dirs:
       src
diff --git a/src/Logging/Aeson.hs b/src/Logging/Aeson.hs
--- a/src/Logging/Aeson.hs
+++ b/src/Logging/Aeson.hs
@@ -17,6 +17,7 @@
 import           Data.Aeson.Types            (Parser, typeMismatch)
 import           Data.Default
 import           Data.Generics.Product.Typed
+import           Data.IORef
 import qualified Data.Map.Lazy               as M
 import           System.Directory
 import           System.FilePath
@@ -27,13 +28,6 @@
 import           Logging.Utils
 
 
-mapAp :: (Applicative f1, Applicative f2) => f1 (a -> b) -> f2 a -> (f1 (f2 b))
-mapAp f x = ((<*> x) . pure) <$> f
-
-mapAp2 :: (Applicative f1, Applicative f2) => f1 (a -> b -> c) -> f2 a -> f2 b -> (f1 (f2 c))
-mapAp2 f x y = ((<*> y). (<*> x) . pure) <$> f
-
-
 {- $aesondoc
 
 By using 'Data.Aeson', we can decode json string into 'Manager'.
@@ -81,7 +75,7 @@
 Note: Besides some common field, handler's other fields depend on its type.
 
 @
-  -- a standard format
+  -- StreamHandler
   {
     \"type\": \"StreamHandler\",
     \"stream\": \"stderr\",
@@ -90,7 +84,7 @@
     \"formatter\": \"default\",
   }
 
-  -- FileHandler is just a StreamHandler, the stream is created by openFile
+  -- FileHandler
   {
     \"type\": \"FileHandler\",
     \"file\": \"./default.log\",
@@ -143,7 +137,7 @@
   parseJSON invalid = typeMismatch "Object" invalid
 
 
-instance FromJSON (StreamHandler) where
+instance FromJSON StreamHandler where
   parseJSON = withObject "StreamHandler" $ \v ->
       StreamHandler <$> (parseStream <$> (v .:? "stream" .!= "stderr"))
                     <*> v .:? "level" .!= def
@@ -156,6 +150,19 @@
       parseStream _        = error "Logging.Aeson: no parse (stream)"
 
 
+instance FromJSON (IO FileHandler) where
+  parseJSON = withObject "FileHandler" $ \v -> do
+    file <- v .:? "file" .!= "log4hs.log"
+    encoding <- v .:? "encoding" .!= (show utf8)
+    level <- v .:? "level" .!= def
+    filterer <- v .:? "filterer" .!= []
+    formatter <- v .:? "formatter" .!= def
+    return $ do
+      stream <- newIORef undefined
+      encoding' <- mkTextEncoding encoding
+      return $ FileHandler stream file encoding' level filterer formatter
+
+
 instance FromJSON (IO SomeHandler) where
   parseJSON = withObject "Handler" $ \v -> (v .: "type") >>= (`parseHandler` v)
     where
@@ -164,10 +171,8 @@
         hdl <- parseJSON (Object v)
         return $ return $ toHandler (hdl :: StreamHandler)
       parseHandler "FileHandler" v = do
-        hdl <- parseJSON (Object v)
-        file <- v .: "file" .!= "default.log"
-        return $ openLogFile file utf8 >>= \stream -> return $
-          toHandler (hdl {stream = stream} :: StreamHandler)
+        hdlIo <- parseJSON (Object v)
+        return $ toHandler <$> (hdlIo :: IO FileHandler)
 
 
 instance FromJSON (M.Map String Formatter -> IO SomeHandler) where
diff --git a/src/Logging/Types/Class/Handler.hs b/src/Logging/Types/Class/Handler.hs
--- a/src/Logging/Types/Class/Handler.hs
+++ b/src/Logging/Types/Class/Handler.hs
@@ -40,9 +40,11 @@
   (SomeHandler h1) == h2 = Just h1 == fromHandler h2
 
 instance Handler SomeHandler where
+  open (SomeHandler h) = open h
   emit (SomeHandler h) = emit h
   flush (SomeHandler h) = flush h
   close (SomeHandler h) = close h
+  handle (SomeHandler h) = handle h
   fromHandler = Just . id
   toHandler = id
 
diff --git a/src/Logging/Types/Handlers.hs b/src/Logging/Types/Handlers.hs
--- a/src/Logging/Types/Handlers.hs
+++ b/src/Logging/Types/Handlers.hs
@@ -1,5 +1,7 @@
 module Logging.Types.Handlers
   ( module Logging.Types.Handlers.StreamHandler
+  , module Logging.Types.Handlers.FileHandler
   ) where
 
+import           Logging.Types.Handlers.FileHandler
 import           Logging.Types.Handlers.StreamHandler
diff --git a/src/Logging/Types/Handlers/FileHandler.hs b/src/Logging/Types/Handlers/FileHandler.hs
new file mode 100644
--- /dev/null
+++ b/src/Logging/Types/Handlers/FileHandler.hs
@@ -0,0 +1,41 @@
+{-# LANGUAGE DeriveGeneric         #-}
+{-# LANGUAGE DuplicateRecordFields #-}
+{-# LANGUAGE RecordWildCards       #-}
+
+module Logging.Types.Handlers.FileHandler
+  ( FileHandler(..)
+  ) where
+
+import           Data.IORef
+import           GHC.Generics
+import           System.IO
+
+import           Logging.Types.Class
+import           Logging.Types.Filter
+import           Logging.Types.Formatter
+import           Logging.Types.Level
+import           Logging.Utils
+import           System.IO.Extra
+
+
+-- | A handler type which writes logging records, appropriately formatted,
+-- to a file.
+--
+data FileHandler = FileHandler { stream    :: IORef Handle
+                               , file      :: FilePath
+                               , encoding  :: TextEncoding
+                               , level     :: Level
+                               , filterer  :: Filterer
+                               , formatter :: Formatter
+                               } deriving (Generic, Eq)
+
+instance Handler FileHandler where
+  open FileHandler{..} = atomicWriteIORef stream =<< openLogFile file encoding
+
+  emit self@FileHandler{..} rcd = do
+    flip hPutStrLn (format formatter rcd) =<< readIORef stream
+    flush self
+
+  flush FileHandler{..}= hFlush =<< readIORef stream
+
+  close FileHandler{..} = hClose =<< readIORef stream
diff --git a/src/Logging/Types/Handlers/StreamHandler.hs b/src/Logging/Types/Handlers/StreamHandler.hs
--- a/src/Logging/Types/Handlers/StreamHandler.hs
+++ b/src/Logging/Types/Handlers/StreamHandler.hs
@@ -17,10 +17,6 @@
 -- | A handler type which writes logging records, appropriately formatted,
 -- to a stream.
 --
--- Note that this class does not close the stream when the stream is a
--- terminal device, e.g. 'stderr' and 'stdout'.
---
--- Note: 'FileHandler' is an alias of 'StreamHandler'
 data StreamHandler = StreamHandler { stream    :: Handle
                                    , level     :: Level
                                    , filterer  :: Filterer
diff --git a/src/System/IO/Extra.hs b/src/System/IO/Extra.hs
new file mode 100644
--- /dev/null
+++ b/src/System/IO/Extra.hs
@@ -0,0 +1,7 @@
+module System.IO.Extra  where
+
+import           System.IO
+
+
+instance Eq TextEncoding where
+  e1 == e2 = show e1 == show e2
diff --git a/test/Logging/AesonSpec.hs b/test/Logging/AesonSpec.hs
--- a/test/Logging/AesonSpec.hs
+++ b/test/Logging/AesonSpec.hs
@@ -85,6 +85,25 @@
     filterer == [Filter "Module.Submodule"] `shouldBe` True
     formatter == def {fmt = "default"} `shouldBe` True
 
+  it "decode FileHandler" $ do
+    FileHandler{..} <- fromJust $ decode $ encode $
+          [aesonQQ|
+            {
+              "type": "FileHandler",
+              "file": "myapp.log",
+              "encoding": "UTF-16",
+              "level": "INFO",
+              "filterer": ["Module.Submodule"],
+              "formatter": "default"
+            }
+          |]
+
+    file `shouldBe` "myapp.log"
+    encoding `shouldBe` utf16
+    level `shouldBe` "INFO"
+    filterer == [Filter "Module.Submodule"] `shouldBe` True
+    formatter == def {fmt = "default"} `shouldBe` True
+
   it "decode (formatters -> SomeHandler)" $ do
     let simple = def {fmt = "%(logger)s: %(message)s"}
         func = fromJust $ decode $ encode
