System.IO
| Авторские права | (c) Университет Глазго 2001 |
|---|---|
| Лицензия | BSD (см. файл libraries/base/LICENSE) |
| Поддержка | libraries@haskell.org |
| Устойчивость | стабильная |
| Переносимость | переносимая |
| Safe Haskell | Надёжная |
| Язык | Haskell2010 |
Содержание
Описание
Стандартная библиотека ввода-вывода.
Монад IO
data IO a :: * -> * Исходный код
Значение типа IO a представляет собой вычисление, которое при выполнении выполняет некоторое ввод-вывод, прежде чем вернуть значение типа a.
Существует только один способ «выполнить» действие ввода-вывода: связать его с Main.main в вашей программе. При запуске программы ввод-вывод будет выполнен. Невозможно выполнить ввод-вывод из произвольной функции, если только эта функция сама не находится в IO монаде и не вызывается в какой-то момент, прямо или косвенно, из Main.main.
IO является монадой, поэтому действия IO можно комбинировать, используя либо синтаксис do, либо операции >> и >>= из класса Monad.
Примеры реализации
| Monad IO | |
| Functor IO | |
| MonadFix IO | |
| Applicative IO | |
| (~) * a () => HPrintfType (IO a) | |
| (~) * a () => PrintfType (IO a) |
fixIO :: (a -> IO a) -> IO a Исходный код
Файлы и дескрипторы
type FilePath = String Исходный код
Имена файлов и каталогов — это значения типа String, точное значение которого зависит от операционной системы. Файлы могут быть открыты, что приводит к получению дескриптора, который затем можно использовать для работы с содержимым этого файла.
data Handle Исходный код
Haskell определяет операции для чтения и записи символов из и в файлы, представленные значениями типа Handle. Каждое значение этого типа является дескриптором: записью, используемой системой выполнения Haskell для управления вводом-выводом с объектами файловой системы. Дескриптор имеет, как минимум, следующие свойства:
- управление вводом, выводом или обоими;
- является открытым, закрытым или полузакрытым;
- является ли объект позиционируемым;
- отключена буферизация или она включена на основе строк или блоков;
- буфер (длина которого может быть нулевой).
Большинство дескрипторов также будут иметь текущую позицию ввода-вывода, указывающую, где произойдёт следующая операция ввода или вывода. Дескриптор является читаемым, если он управляет только вводом или и вводом, и выводом; аналогично, он является записываемым, если он управляет только выводом или и вводом, и выводом. Дескриптор является открытым при первом выделении. После закрытия его нельзя больше использовать ни для ввода, ни для вывода, хотя реализация не может повторно использовать его хранилище, пока на него ссылаются. Дескрипторы находятся в классах Show и Eq. Строка, полученная при отображении дескриптора, зависит от системы; она должна содержать достаточную информацию для идентификации дескриптора для отладки. Два дескриптора равны в соответствии с == только в том случае, если они идентичны; не предпринимается попыток сравнить внутреннее состояние различных дескрипторов на равенство.
Примечание GHC: дескриптор Handle будет автоматически закрыт, когда сборщик мусора обнаружит, что на него больше нет ссылок в программе. Однако, полагаться на это поведение не рекомендуется: поведение сборщика мусора непредсказуемо. Если возможно, используйте явное hClose, чтобы закрыть Handle при необходимости.
Стандартные дескрипторы
Три дескриптора выделяются при инициализации программы и изначально открыты.
Дескриптор, управляющий вводом из стандартного канала ввода Haskell-программы.
Дескриптор, управляющий выводом в стандартный канал вывода Haskell-программы.
Дескриптор, управляющий выводом в стандартный канал ошибок Haskell-программы.
Открытие и закрытие файлов
Открытие файлов
withFile :: FilePath -> IOMode -> (Handle -> IO r) -> IO r Исходный код
withFile name mode act открывает файл с помощью openFile и передает полученный дескриптор в вычисление act. Дескриптор будет закрыт при выходе из withFile, независимо от того, нормальным ли завершением это произошло, или было вызвано исключением. Если закрытие дескриптора вызывает исключение, то это исключение будет вызвано withFile вместо любого исключения, вызванного act.
openFile :: FilePath -> IOMode -> IO Handle Исходный код
Вычисление openFile file mode выделяет и возвращает новый открытый дескриптор для управления файлом file. Он управляет вводом, если mode равно ReadMode, выводом, если mode равно WriteMode или AppendMode, и и вводом, и выводом, если режим равен ReadWriteMode.
Если файл не существует и открыт для вывода, он должен быть создан как новый файл. Если mode равен WriteMode и файл уже существует, он должен быть усечён до нулевой длины. Некоторые операционные системы удаляют пустые файлы, поэтому нет гарантии, что файл будет существовать после openFile с mode WriteMode, если он не будет успешно записан позже. Дескриптор позиционируется в конце файла, если mode равно AppendMode, и в противном случае в начале (в этом случае его внутренняя позиция равна 0). Начальный режим буфера зависит от реализации.
Эта операция может завершиться ошибкой:
-
isAlreadyInUseErrorесли файл уже открыт и не может быть повторно открыт; -
isDoesNotExistErrorесли файл не существует; или -
isPermissionErrorесли у пользователя нет разрешения на открытие файла.
Примечание: если вы будете работать с файлами, содержащими двоичные данные, вам следует использовать openBinaryFile.
data IOMode Исходный код
См. openFile
Конструкторы
| ReadMode | |
| WriteMode | |
| AppendMode | |
| ReadWriteMode |
Закрытие файлов
hClose :: Handle -> IO () Source
Вычисление hClose hdl делает дескриптор файла hdl закрытым. Перед завершением вычисления, если дескриптор hdl является выходным, его буфер сбрасывается так же, как для hFlush. Выполнение hClose для уже закрытого дескриптора не оказывает никакого влияния; это не ошибка. Все остальные операции с закрытым дескриптором завершатся неудачно. Если hClose завершится неудачно по какой-либо причине, любые дальнейшие операции (кроме hClose) с дескриптором все равно завершатся неудачей, как если бы hdl был успешно закрыт.
Особые случаи
Эти функции также экспортированы в Prelude.
readFile :: FilePath -> IO String Source
Функция readFile считывает файл и возвращает содержимое файла в виде строки. Файл считывается лениво, по требованию, как и с getContents.
writeFile :: FilePath -> String -> IO () Source
Вычисление writeFile file str функции записывает строку str, в файл file.
appendFile :: FilePath -> String -> IO () Source
Вычисление appendFile file str функции добавляет строку str, к файлу file.
Обратите внимание, что writeFile и appendFile записывают литеральную строку в файл. Чтобы записать значение любого печатного типа, как с print, сначала используйте функцию show для преобразования значения в строку.
main = appendFile "squares" (show [(x,x*x) | x <- [0,0.1..2]])
Блокировка файлов
Реализации должны по возможности, по крайней мере локально для процесса Haskell, обеспечивать блокировку множественного чтения и одиночного записи для файлов. То есть, может быть много дескрипторов на одном и том же файле, управляющих вводом, или только один дескриптор файла, управляющий выводом. Если любой открытый или полузакрытый дескриптор управляет файлом для вывода, новый дескриптор не может быть выделен для этого файла. Если любой открытый или полузакрытый дескриптор управляет файлом для ввода, новые дескрипторы могут быть выделены только в том случае, если они не управляют выводом. Являются ли два файла одинаковыми, зависит от реализации, но они обычно должны быть одинаковыми, если у них есть одинаковое абсолютное имя пути и ни один из них не был переименован, например.
Предупреждение: операция readFile удерживает полузакрытый дескриптор файла до тех пор, пока все содержимое файла не будет израсходовано. Следовательно, попытка записи в файл (например, с помощью writeFile), который ранее был открыт с помощью readFile, обычно приведет к ошибке с isAlreadyInUseError.
Операции с дескрипторами
Определение и изменение размера файла
hFileSize :: Handle -> IO Integer Source
Для дескриптора файла hdl, присоединенного к физическому файлу, hFileSize hdl возвращает размер этого файла в байтах по 8 бит.
hSetFileSize :: Handle -> Integer -> IO () Source
hSetFileSize hdl size обрезает физический файл с дескриптором hdl до size байтов.
Обнаружение конца ввода
hIsEOF :: Handle -> IO Bool Source
Для читаемого дескриптора файла hdl, hIsEOF hdl возвращает True, если дальнейший ввод не может быть получен из hdl или для физического файла, если текущая позиция ввода-вывода равна длине файла. В противном случае возвращается False.
ПРИМЕЧАНИЕ: hIsEOF может заблокироваться, потому что ему нужно попытаться прочитать из потока, чтобы определить, есть ли больше данных для чтения.
Вычисление isEOF идентично hIsEOF, за исключением того, что оно работает только на stdin.
Операции буферизации
data BufferMode Source
Поддерживаются три типа буферизации: буферизация строк, буферизация блоков или отсутствие буферизации. Эти режимы имеют следующие эффекты. Для вывода элементы выводятся или сбрасываются из внутреннего буфера в соответствии с режимом буферизации:
-
буферизация строк: весь буфер вывода сбрасывается всякий раз, когда выводится символ новой строки, буфер переполняется, вызывается
hFlushили закрывается дескриптор файла. -
буферизация блоков: весь буфер записывается, когда он переполняется, вызывается
hFlushили закрывается дескриптор файла. - без буферизации: вывод записывается немедленно и никогда не хранится в буфере.
Реализация может сбрасывать буфер чаще, но не реже, чем указано выше. Буфер вывода опустошается сразу после записи.
Аналогично, ввод происходит в соответствии с режимом буферизации для дескриптора файла:
- буферизация строк: когда буфер дескриптора файла не пуст, следующий элемент берется из буфера; в противном случае, когда буфер пуст, символы до и включая следующий символ новой строки считываются в буфер. Никакие символы недоступны, пока символ новой строки не станет доступным или буфер не заполнится.
- буферизация блоков: когда буфер дескриптора файла становится пустым, следующий блок данных считывается в буфер.
-
без буферизации: следующий элемент ввода считывается и возвращается. Операция
hLookAheadподразумевает, что даже дескриптор без буферизации может потребовать буфер на один символ.
Установленный по умолчанию режим буферизации при открытии дескриптора зависит от реализации и может зависеть от объекта файловой системы, связанного с этим дескриптором. Для большинства реализаций физические файлы обычно буферизируются блоками, а терминалы обычно буферизируются строками.
Конструкторы
| NoBuffering | буферизация отключена, если это возможно. |
| LineBuffering | буферизация строк должна быть включена, если это возможно. |
| BlockBuffering (Maybe Int) | буферизация блоков должна быть включена, если это возможно. Размер буфера равен |
Примеры реализации
hSetBuffering :: Handle -> BufferMode -> IO () Source
Вычисление hSetBuffering hdl mode устанавливает режим буферизации для дескриптора hdl при последующих операциях чтения и записи.
Если режим буферизации изменяется с BlockBuffering или LineBuffering на NoBuffering, то
- если
hdlдоступен для записи, буфер очищается, как дляhFlush; - если
hdlнедоступен для записи, содержимое буфера отбрасывается.
Данная операция может завершиться неудачей с:
-
isPermissionErrorесли дескриптор уже был использован для чтения или записи, и реализация не позволяет изменить режим буферизации.
hGetBuffering :: Handle -> IO BufferMode Source
Вычисление hGetBuffering hdl возвращает текущий режим буферизации для hdl.
hFlush :: Handle -> IO () Source
Действие hFlush hdl вызывает немедленную отправку в операционную систему всех элементов, буферизованных для вывода в дескрипторе hdl.
Данная операция может завершиться неудачей с:
-
isFullErrorесли устройство заполнено; -
isPermissionErrorесли будет превышен лимит системных ресурсов. В этом случае не определено, будут ли символы в буфере отброшены или сохранены.
Перемещение дескрипторов
hGetPosn :: Handle -> IO HandlePosn Source
Вычисление hGetPosn hdl возвращает текущую позицию ввода-вывода для hdl как значение абстрактного типа HandlePosn.
hSetPosn :: HandlePosn -> IO () Source
Если вызов hGetPosn hdl возвращает позицию p, то вычисление hSetPosn p устанавливает позицию hdl на позицию, которую она занимала в момент вызова hGetPosn.
Данная операция может завершиться неудачей с:
-
isPermissionErrorесли будет превышен лимит системных ресурсов.
data HandlePosn Source
Реализации
hSeek :: Handle -> SeekMode -> Integer -> IO () Source
Вычисление hSeek hdl mode i устанавливает позицию дескриптора hdl в зависимости от mode. Смещение i задается в байтах.
Если hdl имеет буферизацию по блокам или строкам, то перемещение к позиции, не содержащейся в текущем буфере, вызовет сначала запись всех элементов буфера вывода на устройство, а затем отбросит буфер ввода. Некоторые дескрипторы могут не поддерживать перемещение (см. hIsSeekable), или поддерживать только подмножество возможных операций позиционирования (например, может быть возможно перемещение только к концу ленты или к смещению относительно начала или текущей позиции). Невозможно установить отрицательную позицию ввода-вывода или позицию ввода-вывода физического файла, превышающую текущий конец файла.
Данная операция может завершиться неудачей с:
-
isIllegalOperationErrorесли дескриптор не поддерживает перемещение или не поддерживает запрошенный режим перемещения. -
isPermissionErrorесли будет превышен лимит системных ресурсов.
Режим, определяющий действие hSeek hdl mode i.
Конструкторы
| AbsoluteSeek | позиция |
| RelativeSeek | позиция |
| SeekFromEnd | позиция |
hTell :: Handle -> IO Integer Source
Вычисление hTell hdl возвращает текущую позицию дескриптора hdl, как количество байтов от начала файла. Возвращённое значение может быть затем передано в hSeek для перемещения дескриптора в текущую позицию.
Данная операция может завершиться неудачей с:
-
isIllegalOperationErrorесли дескриптор не поддерживает перемещение.
Свойства дескрипторов
hIsOpen :: Handle -> IO Bool Source
hIsClosed :: Handle -> IO Bool Source
hIsReadable :: Handle -> IO Bool Source
hIsWritable :: Handle -> IO Bool Source
hIsSeekable :: Handle -> IO Bool Source
Операции с терминалом (не переносимая: только GHC)
hIsTerminalDevice :: Handle -> IO Bool Source
Подключен ли дескриптор к терминалу?
hSetEcho :: Handle -> Bool -> IO () Source
Установить состояние эха для дескриптора, подключенного к терминалу.
hGetEcho :: Handle -> IO Bool Source
Получить состояние эха для дескриптора, подключенного к терминалу.
Отображение состояния дескриптора (не переносимая: только GHC)
hShow :: Handle -> IO String Source
hShow находится в IO монаде и дает более полный вывод, чем (чистый) экземпляр Show для Handle.
Текстовый ввод и вывод
Текстовый ввод
hWaitForInput :: Handle -> Int -> IO Bool Source
Вычисление hWaitForInput hdl t ожидает, пока ввод не станет доступен в дескрипторе hdl. Оно возвращает True, как только ввод становится доступен в hdl, или False, если ввод недоступен в течение t миллисекунд. Обратите внимание, что hWaitForInput ожидает, пока не станут доступны один или несколько полных символов, что означает, что ему необходимо выполнить декодирование, и поэтому он может завершиться ошибкой декодирования.
Если t меньше нуля, то hWaitForInput ожидает неопределенно долго.
Эта операция может завершиться ошибкой:
-
isEOFErrorесли достигнут конец файла. - ошибка декодирования, если ввод начинается с недопустимой последовательности байтов в кодировке этого дескриптора.
ПРИМЕЧАНИЕ для пользователей GHC: если вы не используете флаг -threaded, hWaitForInput hdl t, где t >= 0 будет блокировать все остальные потоки Haskell на время вызова. В этом отношении он ведет себя как внешний вызов safe.
hReady :: Handle -> IO Bool Source
Вычисление hReady hdl указывает, доступен ли хотя бы один элемент для ввода из дескриптора hdl.
Эта операция может завершиться ошибкой:
-
isEOFErrorесли достигнут конец файла.
hGetChar :: Handle -> IO Char Source
Вычисление hGetChar hdl считывает символ из файла или канала, управляемого hdl, блокируя до тех пор, пока символ не станет доступен.
Эта операция может завершиться ошибкой:
-
isEOFErrorесли достигнут конец файла.
hGetLine :: Handle -> IO String Source
Вычисление hGetLine hdl считывает строку из файла или канала, управляемого hdl.
Эта операция может завершиться ошибкой:
-
isEOFErrorесли при чтении первого символа строки встречен конец файла.
Если hGetLine встречает конец файла в любой другой точке при чтении строки, это рассматривается как разделитель строки, и возвращается (частичная) строка.
hLookAhead :: Handle -> IO Char Source
Вычисление hLookAhead возвращает следующий символ из дескриптора, не удаляя его из буфера ввода, блокируя до тех пор, пока символ не станет доступен.
Эта операция может завершиться ошибкой:
-
isEOFErrorесли достигнут конец файла.
hGetContents :: Handle -> IO String Source
Вычисление hGetContents hdl возвращает список символов, соответствующих непрочитанной части канала или файла, управляемого hdl, который переводится в промежуточное состояние, полузакрытое. В этом состоянии hdl эффективно закрыт, но элементы считываются из hdl по требованию и накапливаются в специальном списке, возвращаемом hGetContents hdl.
Любая операция, которая завершается ошибкой из-за закрытия дескриптора, также завершается ошибкой, если дескриптор полузакрыт. Единственным исключением является hClose. Полузакрытый дескриптор закрывается:
- если к нему применяется
hClose; - если возникает ошибка ввода-вывода при чтении элемента из дескриптора;
- или после того, как все содержимое дескриптора будет считано.
После того как полузакрытый дескриптор закрывается, содержимое связанного списка становится фиксированным. Содержимое этого окончательного списка частично определено: оно будет содержать по крайней мере все элементы потока, которые были оценены до закрытия дескриптора.
Любые ошибки ввода-вывода, обнаруженные, пока дескриптор полузакрыт, просто игнорируются.
Эта операция может завершиться ошибкой:
-
isEOFErrorесли достигнут конец файла.
Текстовый вывод
hPutChar :: Handle -> Char -> IO () Source
Вычисление hPutChar hdl ch записывает символ ch в файл или канал, управляемый hdl. Символы могут буферизоваться, если буферизация включена для hdl.
Эта операция может завершиться ошибкой:
-
isFullErrorесли устройство заполнено; или -
isPermissionErrorесли будет превышен другой системный ресурсный лимит.
hPutStr :: Handle -> String -> IO () Source
Вычисление hPutStr hdl s записывает строку s в файл или канал, управляемый hdl.
Эта операция может завершиться ошибкой:
-
isFullErrorесли устройство заполнено; или -
isPermissionErrorесли будет превышен другой системный ресурсный лимит.
hPutStrLn :: Handle -> String -> IO () Source
То же самое, что и hPutStr, но добавляет символ новой строки.
hPrint :: Show a => Handle -> a -> IO () Source
Вычисление hPrint hdl t записывает строковое представление t, заданное функцией shows, в файл или канал, управляемый hdl, и добавляет символ новой строки.
Эта операция может завершиться ошибкой:
-
isFullErrorесли устройство заполнено; или -
isPermissionErrorесли будет превышен другой системный ресурсный лимит.
Специальные случаи для стандартного ввода и вывода
Эти функции также экспортируются Prelude.
interact :: (String -> String) -> IO () Source
Функция interact принимает в качестве аргумента функцию типа String->String. Весь ввод со стандартного устройства ввода передается этой функции в качестве аргумента, а результирующая строка выводится на стандартное устройство вывода.
putChar :: Char -> IO () Source
Записать символ на стандартное устройство вывода (то же самое, что и hPutChar stdout).
putStr :: String -> IO () Source
Записать строку на стандартное устройство вывода (то же самое, что и hPutStr stdout).
putStrLn :: String -> IO () Source
То же самое, что и putStr, но добавляет символ новой строки.
print :: Show a => a -> IO () Source
Функция print выводит значение любого печатаемого типа на стандартное устройство вывода. Печатаемые типы — это те, которые являются экземплярами класса Show; print преобразует значения в строки для вывода с помощью операции show и добавляет символ новой строки.
Например, программу для вывода первых 20 целых чисел и их степеней 2 можно написать так:
main = print ([(n, 2^n) | n <- [0..19]])
Считывает символ со стандартного устройства ввода (аналогично hGetChar stdin).
Считывает строку со стандартного устройства ввода (аналогично hGetLine stdin).
getContents :: IO String Source
Операция getContents возвращает весь введённый пользователем текст как одну строку, которая считывается лениво по мере необходимости (аналогично hGetContents stdin).
readIO :: Read a => String -> IO a Source
Функция readIO похожа на read, за исключением того, что она сигнализирует об ошибке разбора в монаде IO, а не завершает программу.
readLn :: Read a => IO a Source
Функция readLn объединяет getLine и readIO.
Ввод и вывод двоичных данных
withBinaryFile :: FilePath -> IOMode -> (Handle -> IO r) -> IO r Source
withBinaryFile name mode act открывает файл в режиме openBinaryFile и передаёт полученный дескриптор вычислению act. Дескриптор будет закрыт при завершении withBinaryFile, независимо от того, было ли это нормальным завершением или возникновением исключения.
openBinaryFile :: FilePath -> IOMode -> IO Handle Source
Аналогично openFile, но открывает файл в двоичном режиме. В Windows, чтение файла в текстовом режиме (по умолчанию) преобразует CRLF в LF, а запись преобразует LF в CRLF. Это обычно то, что нужно для текстовых файлов. В случае с двоичными файлами это нежелательно; также, как обычно в системах Microsoft, текстовый режим считает символ Control-Z как EOF. Двоичный режим отключает все специальное обращение с символами конца строки и конца файла. (См. также hSetBinaryMode.)
hSetBinaryMode :: Handle -> Bool -> IO () Source
Устанавливает двоичный режим (True) или текстовый режим (False) для открытого дескриптора. (См. также openBinaryFile.)
Это эквивалентно вызову hSetEncoding с char8, вместе с hSetNewlineMode с noNewlineTranslation.
hPutBuf :: Handle -> Ptr a -> Int -> IO () Source
hPutBuf hdl buf count записывает count 8-битных байтов из буфера buf в дескриптор hdl. Возвращает ().
hPutBuf игнорирует любые кодировки, которые могут применяться к Handle, записывая байты напрямую в подлежащий файл или устройство.
hPutBuf игнорирует действующую TextEncoding и NewlineMode на Handle, и записывает байты напрямую.
Эта операция может завершиться неудачно:
-
ResourceVanishedесли дескриптор является конвейром или сокетом, и конец для чтения закрыт. (Если это POSIX-система, и программа не запросила игнорирование SIGPIPE, то вместо этого может быть отправлено SIGPIPE, стандартное действие которого — завершить программу).
hGetBuf :: Handle -> Ptr a -> Int -> IO Int Source
hGetBuf hdl buf count считывает данные из дескриптора hdl в буфер buf до тех пор, пока не достигнет конца файла или не будет прочитано count 8-битных байтов. Возвращает количество фактически прочитанных байтов. Может быть равно нулю, если конец файла достигнут до чтения любых данных (или если count равно нулю).
hGetBuf никогда не вызывает исключение EOF, вместо этого возвращает значение меньше count.
Если дескриптор является конвейром или сокетом, и конец для записи закрыт, hGetBuf будет вести себя так, как будто достигнут конец файла.
hGetBuf игнорирует действующую TextEncoding и NewlineMode на Handle, и считывает байты напрямую.
hGetBufSome :: Handle -> Ptr a -> Int -> IO Int Source
hGetBufSome hdl buf count считывает данные из дескриптора hdl в буфер buf. Если какие-либо данные доступны для чтения, то hGetBufSome возвращает их немедленно; блокируется только если нет данных для чтения.
Возвращает количество фактически прочитанных байтов. Может быть равно нулю, если конец файла достигнут до чтения любых данных (или если count равно нулю).
hGetBufSome никогда не вызывает исключение EOF, вместо этого возвращает значение меньше count.
Если дескриптор является конвейром или сокетом, и конец для записи закрыт, hGetBufSome будет вести себя так, как будто достигнут конец файла.
hGetBufSome игнорирует действующую TextEncoding и NewlineMode на Handle, и считывает байты напрямую.
hPutBufNonBlocking :: Handle -> Ptr a -> Int -> IO Int Source
hGetBufNonBlocking :: Handle -> Ptr a -> Int -> IO Int Source
hGetBufNonBlocking hdl buf count считывает данные из дескриптора hdl в буфер buf до тех пор, пока не достигнет конца файла, или не будет прочитано count 8-битных байтов, или пока нет доступных данных для немедленного чтения.
hGetBufNonBlocking идентично hGetBuf, за исключением того, что она никогда не будет блокироваться в ожидании появления данных, а возвращает только те данные, которые доступны. Чтобы подождать появления данных перед вызовом hGetBufNonBlocking, используйте hWaitForInput.
Если дескриптор является конвейром или сокетом, и конец для записи закрыт, hGetBufNonBlocking будет вести себя так, как будто достигнут конец файла.
hGetBufNonBlocking игнорирует действующую TextEncoding и NewlineMode на Handle, и считывает байты напрямую.
ПРИМЕЧАНИЕ: в Windows эта функция работает некорректно; она ведет себя идентично hGetBuf.
Временные файлы
Аргументы
| :: FilePath | Директория, в которой должен быть создан файл |
| -> String | Шаблон имени файла. Если шаблон "foo.ext", то создаваемый файл будет "fooXXX.ext", где XXX — некоторое случайное число. |
| -> IO (FilePath, Handle) |
Функция создаёт временный файл в режиме чтения/записи. Созданный файл не удаляется автоматически, поэтому вам необходимо удалить его вручную.
Файл создаётся с разрешениями, позволяющими только текущему пользователю читать/писать в него.
В некоторых случаях (см. ниже), файл будет создан безопасно в том смысле, что злоумышленник не сможет заставить openTempFile перезаписать другой файл в файловой системе, используя ваши учетные данные, разместив символические ссылки (в Unix) в месте, где должен быть создан временный файл. В Unix используются флаги O_CREAT и O_EXCL для предотвращения этой атаки, но обратите внимание, что O_EXCL иногда не поддерживается на NFS файловых системах, поэтому если вы полагаетесь на это поведение, лучше использовать только локальные файловые системы.
openBinaryTempFile :: FilePath -> String -> IO (FilePath, Handle) Source
Как openTempFile, но открывает файл в бинарном режиме. См. openBinaryFile для дополнительных комментариев.
openTempFileWithDefaultPermissions :: FilePath -> String -> IO (FilePath, Handle) Source
Как openTempFile, но использует права доступа по умолчанию.
openBinaryTempFileWithDefaultPermissions :: FilePath -> String -> IO (FilePath, Handle) Source
Как openBinaryTempFile, но использует права доступа по умолчанию.
Кодирование/декодирование Unicode
Поток в текстовом режиме Handle имеет ассоциированную TextEncoding, которая используется для декодирования байтов в символы Unicode при чтении и кодирования символов Unicode в байты при записи.
Кодировка по умолчанию TextEncoding совпадает с кодировкой по умолчанию вашей системы, которая также доступна как localeEncoding. (Примечание GHC: в Windows мы в настоящее время не поддерживаем двухбайтовые кодировки; если кодовая страница консоли не поддерживается, то localeEncoding будет latin1.)
Ошибки кодирования и декодирования всегда обнаруживаются и сообщаются, за исключением ленивого ввода-вывода (hGetContents, getContents и readFile), где ошибка декодирования просто приводит к завершению потока символов, как и другие ошибки ввода-вывода.
hSetEncoding :: Handle -> TextEncoding -> IO () Source
Действие hSetEncoding hdl encoding изменяет текстовую кодировку для дескриптора hdl на encoding. Кодировка по умолчанию при создании Handle — это localeEncoding, а именно кодировка по умолчанию для текущей локали.
Чтобы создать Handle без какой-либо кодировки, используйте openBinaryFile. Чтобы остановить дальнейшее кодирование или декодирование существующего Handle, используйте hSetBinaryMode.
hSetEncoding может потребоваться очистить буферизованные данные, чтобы изменить кодировку.
hGetEncoding :: Handle -> IO (Maybe TextEncoding) Source
Возвращает текущую TextEncoding для указанного Handle, или Nothing, если Handle находится в бинарном режиме.
Обратите внимание, что TextEncoding ничего не запоминает о состоянии используемого кодера/декодера в этом Handle. Например, если используется кодировка UTF-16, то использование hGetEncoding и hSetEncoding для сохранения и восстановления кодировки может привести к записи в файл дополнительной метки порядка байтов.
Кодировки Unicode
data TextEncoding Source
TextEncoding — это спецификация схемы преобразования между последовательностями байтов и последовательностями символов Unicode.
Например, UTF-8 — это кодировка символов Unicode в последовательность байтов. TextEncoding для UTF-8 — это utf8.
Экземпляры
Кодировка Latin1 (ISO8859-1). Эта кодировка напрямую отображает байты на первые 256 кодовых точек Unicode и, таким образом, не является полной кодировкой Unicode. Попытка записать символ больше, чем '\255', в Handle с использованием кодировки latin1 приведет к ошибке.
Кодировка Unicode UTF-8
utf8_bom :: TextEncoding Source
Кодировка Unicode UTF-8 с меткой порядка байтов (BOM; байтовая последовательность 0xEF 0xBB 0xBF). Эта кодировка ведет себя как utf8, за исключением того, что на входе последовательность BOM игнорируется в начале потока, а на выходе последовательность BOM добавляется в начало.
Метка порядка байтов строго говоря не является необходимой в UTF-8, но иногда используется для идентификации кодировки файла.
Кодировка Unicode UTF-16 (следует использовать метку порядка байтов для указания порядка байтов).
utf16le :: TextEncoding Source
Кодировка Unicode UTF-16 (little-endian)
utf16be :: TextEncoding Source
Кодировка Unicode UTF-16 (big-endian)
Кодировка Unicode UTF-32 (следует использовать метку порядка байтов для указания порядка байтов).
utf32le :: TextEncoding Source
Кодировка Unicode UTF-32 (little-endian)
utf32be :: TextEncoding Source
Кодировка Unicode UTF-32 (big-endian)
localeEncoding :: TextEncoding Source
Кодировка Unicode текущей локали
Это начальная кодировка локали: если она была впоследствии изменена с помощью setLocaleEncoding, это значение не будет отражать это изменение.
Кодировка, в которой кодовые точки Unicode преобразуются в байты путем взятия кодовой точки по модулю 256. При декодировании байты напрямую преобразуются в эквивалентную кодовую точку.
Эта кодировка никогда не завершается ошибкой ни в одном направлении. Однако кодирование отбрасывает информацию, поэтому кодирование, за которым следует декодирование, не является тождественным преобразованием.
С версии: 4.4.0.0
mkTextEncoding :: String -> IO TextEncoding Source
Ищет именованную кодировку Unicode. Может завершиться ошибкой с
-
isDoesNotExistErrorесли кодировка неизвестна
Набор известных кодировок зависит от системы, но включает как минимум:
UTF-8
-
UTF-16,UTF-16BE,UTF-16LE -
UTF-32,UTF-32BE,UTF-32LE
Существует дополнительная нотация (заимствованная из GNU iconv) для указания того, как обрабатываются недопустимые символы:
- суффикс
//IGNORE, напримерUTF-8//IGNORE, приведет к игнорированию всех недопустимых последовательностей на входе, а на выходе будут отброшены все кодовые точки, которые не имеют представления в целевой кодировке. - суффикс
//TRANSLITвыберет символ замены для недопустимых последовательностей или кодовых точек. - суффикс
//ROUNDTRIPбудет использовать механизм экранирования в стиле PEP383 для представления любых недопустимых байтов на входе как кодовых точек Unicode (в частности, как одиночных суррогатных пар, которые обычно являются недопустимыми в UTF-32). На выходе эти специальные кодовые точки обнаруживаются и преобразуются обратно в соответствующие исходные байты.
Теоретически, этот механизм позволяет произвольным данным проходить через String без потери данных. На практике существуют два ограничения, о которых следует помнить:
- Это может сработать только для кодировок, являющихся расширением ASCII, так как по соображениям безопасности мы отказываемся от экранирования байтов, меньших 128. Многие кодировки, представляющие интерес, являются расширениями ASCII (в частности, вы можете предположить, что кодировка локали является расширением ASCII), но многие (например, UTF-16) таковыми не являются.
- Если основная кодировка сама по себе необратима, этот механизм может потерпеть неудачу. Обратимые кодировки — это те, которые имеют инъективное отображение в Юникод. Почти все кодировки соответствуют этому критерию, но некоторые — нет. Заметим, что Shift-JIS (CP932) и Big5 содержат несколько различных кодировок одного и того же кодового пункта Юникода.
В Windows вы можете получить доступ к поддерживаемым кодовым страницам с префиксом CP; например, "CP1250".
Преобразование символов новой строки
В Haskell новая строка всегда представлена символом '\n'. Однако в файлах и внешних потоках символов новая строка может быть представлена другой последовательностью символов, например, '\r\n'.
В текстовом режиме Handle есть связанный NewlineMode, который определяет, как преобразовывать символы новой строки. NewlineMode указывает перевод вводных и выходных символов новой строки отдельно, так что, например, вы можете переводить '\r\n' в '\n' на входе, но оставлять новые строки как '\n' на выходе.
По умолчанию NewlineMode для Handle — nativeNewlineMode, что не производит преобразования в системах Unix, но преобразует '\r\n' в '\n' и обратно в системах Windows.
В бинарном режиме Handle преобразование символов новой строки не выполняется вообще.
hSetNewlineMode :: Handle -> NewlineMode -> IO () Исходный код
Установите NewlineMode для указанного Handle. Сначала все буферизованные данные сбрасываются.
data Newline Исходный код
Представление символа новой строки во внешнем файле или потоке.
nativeNewline :: Newline Исходный код
Представление символа новой строки по умолчанию для текущей платформы: LF в системах Unix, CRLF в системах Windows.
data NewlineMode Исходный код
Определяет преобразование, если таковое имеется, символов новой строки между внутренними строками и внешним файлом или потоком. Предполагается, что строки Haskell представляют новые строки символом '\n'; режим новой строки определяет, как преобразовать '\n' на выходе и что преобразовать в '\n' на входе.
Конструкторы
| NewlineMode | |
Реализации
noNewlineTranslation :: NewlineMode Исходный код
Не выполнять преобразование символов новой строки вообще.
noNewlineTranslation = NewlineMode { inputNL = LF, outputNL = LF }
universalNewlineMode :: NewlineMode Исходный код
Преобразовать '\r\n' в '\n' на входе и '\n' в символ новой строки по умолчанию на выходе. Этот режим может использоваться на любой платформе и работает с текстовыми файлами, использующими любую конвенцию новых строк. Недостатком является то, что readFile >>= writeFile может привести к получению другого файла.
universalNewlineMode = NewlineMode { inputNL = CRLF,
outputNL = nativeNewline }
nativeNewlineMode :: NewlineMode Исходный код
Использовать родное представление символа новой строки как на входе, так и на выходе.
nativeNewlineMode = NewlineMode { inputNL = nativeNewline
outputNL = nativeNewline }
© The University of Glasgow and others
Licensed under a BSD-style license (see top of the page).
https://downloads.haskell.org/~ghc/7.10.3/docs/html/libraries/base-4.8.2.0/System-IO.html