1{-# LANGUAGE BangPatterns, CPP, RecordWildCards, ScopedTypeVariables #-}
2#if __GLASGOW_HASKELL__ >= 702
3{-# LANGUAGE Trustworthy #-}
6-- Module : Data.Text.IO
7-- Copyright : (c) 2009, 2010 Bryan O'Sullivan,
8-- (c) 2009 Simon Marlow
10-- Maintainer : bos@serpentine.com
11-- Stability : experimental
14-- Efficient locale-sensitive support for text I\/O.
16-- Skip past the synopsis for some important notes on performance and
17-- portability across different versions of GHC.
26 -- * File-at-a-time operations
30 -- * Operations on handles
36 -- * Special cases for standard input and output
44import Data.Text (Text)
45import Prelude hiding (appendFile, getContents, getLine, interact,
46 putStr, putStrLn, readFile, writeFile)
47import System.IO (Handle, IOMode(..), hPutChar, openFile, stdin, stdout,
49import qualified Control.Exception as E
50import Control.Monad (liftM2, when)
51import Data.IORef (readIORef, writeIORef)
52import qualified Data.Text as T
53import Data.Text.Internal.Fusion (stream)
54import Data.Text.Internal.Fusion.Types (Step(..), Stream(..))
55import Data.Text.Internal.IO (hGetLineWith, readChunk)
56import GHC.IO.Buffer (Buffer(..), BufferState(..), CharBufElem, CharBuffer,
57 RawCharBuffer, emptyBuffer, isEmptyBuffer, newCharBuffer,
59import GHC.IO.Exception (IOException(ioe_type), IOErrorType(InappropriateType))
60import GHC.IO.Handle.Internals (augmentIOError, hClose_help, wantReadableHandle,
62import GHC.IO.Handle.Text (commitBuffer')
63import GHC.IO.Handle.Types (BufferList(..), BufferMode(..), Handle__(..),
64 HandleType(..), Newline(..))
65import System.IO (hGetBuffering, hFileSize, hSetBuffering, hTell)
66import System.IO.Error (isEOFError)
71-- The functions in this module obey the runtime system's locale,
72-- character set encoding, and line ending conversion settings.
74-- If you know in advance that you will be working with data that has
75-- a specific encoding (e.g. UTF-8), and your application is highly
76-- performance sensitive, you may find that it is faster to perform
77-- I\/O with bytestrings and to encode and decode yourself than to use
78-- the functions in this module.
80-- Whether this will hold depends on the version of GHC you are using,
81-- the platform you are working on, the data you are working with, and
82-- the encodings you are using, so be sure to test for yourself.
84-- | The 'readFile' function reads a file and returns the contents of
85-- the file as a string. The entire file is read strictly, as with
87readFile :: FilePath -> IO Text
88readFile name = openFile name ReadMode >>= hGetContents
90-- | Write a string to a file. The file is truncated to zero length
91-- before writing begins.
92writeFile :: FilePath -> Text -> IO ()
93writeFile p = withFile p WriteMode . flip hPutStr
95-- | Write a string the end of a file.
96appendFile :: FilePath -> Text -> IO ()
97appendFile p = withFile p AppendMode . flip hPutStr
99catchError :: String -> Handle -> Handle__ -> IOError -> IO Text
100catchError caller h Handle__{..} err
101 | isEOFError err = do
102 buf <- readIORef haCharBuffer
103 return $ if isEmptyBuffer buf
105 else T.singleton '\r'
106 | otherwise = E.throwIO (augmentIOError err caller h)
108-- | /Experimental./ Read a single chunk of strict text from a
109-- 'Handle'. The size of the chunk depends on the amount of input
110-- currently buffered.
112-- This function blocks only if there is no data available, and EOF
113-- has not yet been reached. Once EOF is reached, this function
114-- returns an empty string instead of throwing an exception.
115hGetChunk :: Handle -> IO Text
116hGetChunk h = wantReadableHandle "hGetChunk" h readSingleChunk
118 readSingleChunk hh@Handle__{..} = do
119 buf <- readIORef haCharBuffer
120 t <- readChunk hh buf `E.catch` catchError "hGetChunk" h hh
123-- | Read the remaining contents of a 'Handle' as a string. The
124-- 'Handle' is closed once the contents have been read, or if an
125-- exception is thrown.
127-- Internally, this function reads a chunk at a time from the
128-- lower-level buffering abstraction, and concatenates the chunks into
129-- a single string once the entire file has been read.
131-- As a result, it requires approximately twice as much memory as its
132-- result to construct its result. For files more than a half of
133-- available RAM in size, this may result in memory exhaustion.
134hGetContents :: Handle -> IO Text
136 chooseGoodBuffering h
137 wantReadableHandle "hGetContents" h readAll
139 readAll hh@Handle__{..} = do
141 buf <- readIORef haCharBuffer
142 t <- readChunk hh buf `E.catch` catchError "hGetContents" h hh
145 else (t:) `fmap` readChunks
147 (hh', _) <- hClose_help hh
148 return (hh'{haType=ClosedHandle}, T.concat ts)
150-- | Use a more efficient buffer size if we're reading in
151-- block-buffered mode with the default buffer size. When we can
152-- determine the size of the handle we're reading, set the buffer size
153-- to that, so that we can read the entire file in one chunk.
154-- Otherwise, use a buffer size of at least 16KB.
155chooseGoodBuffering :: Handle -> IO ()
156chooseGoodBuffering h = do
157 bufMode <- hGetBuffering h
159 BlockBuffering Nothing -> do
160 d <- E.catch (liftM2 (-) (hFileSize h) (hTell h)) $ \(e::IOException) ->
161 if ioe_type e == InappropriateType
162 then return 16384 -- faster than the 2KB default
164 when (d > 0) . hSetBuffering h . BlockBuffering . Just . fromIntegral $ d
167-- | Read a single line from a handle.
168hGetLine :: Handle -> IO Text
169hGetLine = hGetLineWith T.concat
171-- | Write a string to a handle.
172hPutStr :: Handle -> Text -> IO ()
173-- This function is lifted almost verbatim from GHC.IO.Handle.Text.
176 wantWritableHandle "hPutStr" h $ \h_ -> do
177 bmode <- getSpareBuffer h_
178 return (bmode, haOutputNL h_)
181 (NoBuffering, _) -> hPutChars h str
182 (LineBuffering, buf) -> writeLines h nl buf str
183 (BlockBuffering _, buf)
184 | nl == CRLF -> writeBlocksCRLF h buf str
185 | otherwise -> writeBlocksRaw h buf str
187hPutChars :: Handle -> Stream Char -> IO ()
188hPutChars h (Stream next0 s0 _len) = loop s0
190 loop !s = case next0 s of
193 Yield x s' -> hPutChar h x >> loop s'
195-- The following functions are largely lifted from GHC.IO.Handle.Text,
196-- but adapted to a coinductive stream of data instead of an inductive
199-- We have several variations of more or less the same code for
200-- performance reasons. Splitting the original buffered write
201-- function into line- and block-oriented versions gave us a 2.1x
202-- performance improvement. Lifting out the raw/cooked newline
203-- handling gave a few more percent on top.
205writeLines :: Handle -> Newline -> Buffer CharBufElem -> Stream Char -> IO ()
206writeLines h nl buf0 (Stream next0 s0 _len) = outer s0 buf0
208 outer s1 Buffer{bufRaw=raw, bufSize=len} = inner s1 (0::Int)
212 Done -> commit n False{-no flush-} True{-release-} >> return ()
213 Skip s' -> inner s' n
215 | n + 1 >= len -> commit n True{-needs flush-} False >>= outer s
218 then do n1 <- writeCharBuf raw n '\r'
219 writeCharBuf raw n1 '\n'
220 else writeCharBuf raw n x
221 commit n' True{-needs flush-} False >>= outer s'
222 | otherwise -> writeCharBuf raw n x >>= inner s'
223 commit = commitBuffer h raw len
225writeBlocksCRLF :: Handle -> Buffer CharBufElem -> Stream Char -> IO ()
226writeBlocksCRLF h buf0 (Stream next0 s0 _len) = outer s0 buf0
228 outer s1 Buffer{bufRaw=raw, bufSize=len} = inner s1 (0::Int)
232 Done -> commit n False{-no flush-} True{-release-} >> return ()
233 Skip s' -> inner s' n
235 | n + 1 >= len -> commit n True{-needs flush-} False >>= outer s
236 | x == '\n' -> do n1 <- writeCharBuf raw n '\r'
237 writeCharBuf raw n1 '\n' >>= inner s'
238 | otherwise -> writeCharBuf raw n x >>= inner s'
239 commit = commitBuffer h raw len
241writeBlocksRaw :: Handle -> Buffer CharBufElem -> Stream Char -> IO ()
242writeBlocksRaw h buf0 (Stream next0 s0 _len) = outer s0 buf0
244 outer s1 Buffer{bufRaw=raw, bufSize=len} = inner s1 (0::Int)
248 Done -> commit n False{-no flush-} True{-release-} >> return ()
249 Skip s' -> inner s' n
251 | n + 1 >= len -> commit n True{-needs flush-} False >>= outer s
252 | otherwise -> writeCharBuf raw n x >>= inner s'
253 commit = commitBuffer h raw len
255-- This function is completely lifted from GHC.IO.Handle.Text.
256getSpareBuffer :: Handle__ -> IO (BufferMode, CharBuffer)
257getSpareBuffer Handle__{haCharBuffer=ref,
262 NoBuffering -> return (mode, error "no buffer!")
264 bufs <- readIORef spare_ref
267 BufferListCons b rest -> do
268 writeIORef spare_ref rest
269 return ( mode, emptyBuffer b (bufSize buf) WriteBuffer)
271 new_buf <- newCharBuffer (bufSize buf) WriteBuffer
272 return (mode, new_buf)
275-- This function is completely lifted from GHC.IO.Handle.Text.
276commitBuffer :: Handle -> RawCharBuffer -> Int -> Int -> Bool -> Bool
278commitBuffer hdl !raw !sz !count flush release =
279 wantWritableHandle "commitAndReleaseBuffer" hdl $
280 commitBuffer' raw sz count flush release
281{-# INLINE commitBuffer #-}
283-- | Write a string to a handle, followed by a newline.
284hPutStrLn :: Handle -> Text -> IO ()
285hPutStrLn h t = hPutStr h t >> hPutChar h '\n'
287-- | The 'interact' function takes a function of type @Text -> Text@
288-- as its argument. The entire input from the standard input device is
289-- passed to this function as its argument, and the resulting string
290-- is output on the standard output device.
291interact :: (Text -> Text) -> IO ()
292interact f = putStr . f =<< getContents
294-- | Read all user input on 'stdin' as a single string.
295getContents :: IO Text
296getContents = hGetContents stdin
298-- | Read a single line of user input from 'stdin'.
300getLine = hGetLine stdin
302-- | Write a string to 'stdout'.
303putStr :: Text -> IO ()
304putStr = hPutStr stdout
306-- | Write a string to 'stdout', followed by a newline.
307putStrLn :: Text -> IO ()
308putStrLn = hPutStrLn stdout
312-- /Note/: The behaviour of functions in this module depends on the
313-- version of GHC you are using.
315-- Beginning with GHC 6.12, text I\/O is performed using the system or
316-- handle's current locale and line ending conventions.
318-- Under GHC 6.10 and earlier, the system I\/O libraries do not
319-- support locale-sensitive I\/O or line ending conversion. On these
320-- versions of GHC, functions in this library all use UTF-8. What
321-- does this mean in practice?
323-- * All data that is read will be decoded as UTF-8.
325-- * Before data is written, it is first encoded as UTF-8.
327-- * On both reading and writing, the platform's native newline
328-- conversion is performed.
330-- If you must use a non-UTF-8 locale on an older version of GHC, you
331-- will have to perform the transcoding yourself, e.g. as follows:
333-- > import qualified Data.ByteString as B
334-- > import Data.Text (Text)
335-- > import Data.Text.Encoding (encodeUtf16)
337-- > putStr_Utf16LE :: Text -> IO ()
338-- > putStr_Utf16LE t = B.putStr (encodeUtf16LE t)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list