System.IO
| Авторские права | (c) Университет Глазго 2001 |
|---|---|
| Лицензия | BSD-стиль (см. файл libraries/base/LICENSE) |
| Поддерживающий | libraries@haskell.org |
| Стабильность | стабильная |
| Переносимость | переносимая |
| Безопасный Haskell | Надёжный |
| Язык | Haskell2010 |
Описание
Стандартная библиотека ввода-вывода.
Монад IO
Значение типа IO a представляет собой вычисление, которое при выполнении выполняет некоторые операции ввода-вывода, прежде чем вернуть значение типа a.
Существует только один способ "выполнить" действие ввода-вывода: связать его с Main.main в вашей программе. При выполнении программы, операции ввода-вывода будут выполнены. Невозможно выполнить операцию ввода-вывода из произвольной функции, если эта функция не находится в IO монаде и вызывается в какой-то момент, непосредственно или косвенно, из Main.main.
IO является монадой, поэтому действия IO можно объединять, используя либо синтаксис do, либо операции >> и >>= из класса Monad.
Экземпляры
| Monad IO | С версии: base-2.1 |
| Functor IO | С версии: base-2.1 |
| MonadFix IO | С версии: base-2.1 |
Определено в Control.Monad.Fix | |
| MonadFail IO | С версии: base-4.9.0.0 |
Определено в Control.Monad.Fail | |
| Applicative IO | С версии: base-2.1 |
| GHCiSandboxIO IO | С версии: base-4.4.0.0 |
Определено в GHC.GHCi МетодыghciStepIO :: IO a -> IO a Источник | |
| MonadPlus IO | С версии: base-4.9.0.0 |
| Alternative IO | С версии: base-4.9.0.0 |
| MonadIO IO | С версии: base-4.9.0.0 |
Определено в Control.Monad.IO.Class | |
| Semigroup a => Semigroup (IO a) | С версии: base-4.10.0.0 |
| Monoid a => Monoid (IO a) | С момента: base-4.9.0.0 |
Определено в GHC.Base Методыmempty :: IO a Исходный код mappend :: IO a -> IO a -> IO a Исходный код mconcat :: [IO a] -> IO a Исходный код | |
| a ~ () => HPrintfType (IO a) | С момента: base-4.7.0.0 |
Определено в Text.Printf | |
| a ~ () => PrintfType (IO a) | С момента: base-4.7.0.0 |
Определено в Text.Printf | |
fixIO :: (a -> IO a) -> IO a Исходный код
Реализация mfix для IO. Если функция, переданная в fixIO, проверяет свой аргумент, то полученное действие выбросит FixIOException.
Файлы и дескрипторы
type FilePath = String Исходный код
Имена файлов и каталогов являются значениями типа String, чьё точное значение зависит от операционной системы. Файлы могут быть открыты, возвращая дескриптор, который затем может использоваться для работы с содержимым этого файла.
data Handle Исходный код
Haskell определяет операции для чтения и записи символов из и в файлы, представленные значениями типа Handle. Каждое значение этого типа является дескриптором: запись, используемая системой Haskell для управления вводом-выводом с файловыми объектами. Дескриптор имеет по крайней мере следующие свойства:
- управление вводом или выводом или обоими;
- является открытым, закрытым или полузакрытым;
- является ли объект позиционируемым;
- буферизация отключена или включена по строкам или блокам;
- буфер (длина которого может быть нулевой).
Большинство дескрипторов также будут иметь текущую позицию ввода-вывода, указывающую, где произойдёт следующая операция ввода или вывода. Дескриптор является читаемым, если он управляет только вводом или обоими вводом и выводом; аналогично, он является записываемым, если он управляет только выводом или обоими вводом и выводом. Дескриптор является открытым при первом выделении. После закрытия его больше нельзя использовать ни для ввода, ни для вывода, хотя реализация не может повторно использовать его хранилище, пока к нему существуют ссылки. Дескрипторы находятся в классах Show и Eq. Строка, полученная путём отображения дескриптора, зависит от системы; она должна содержать достаточно информации, чтобы идентифицировать дескриптор для отладки. Дескриптор равен согласно == только самому себе; не делается попыток сравнить внутреннее состояние разных дескрипторов на равенство.
Экземпляры
| Eq Handle | С момента: base-4.1.0.0 |
Определено в GHC.IO.Handle.Types | |
| Show Handle | С момента: base-4.1.0.0 |
Определено в GHC.IO.Handle.Types МетодыshowsPrec :: Int -> Handle -> ShowS Исходный код show :: Handle -> String Исходный код showList :: [Handle] -> ShowS Исходный код | |
Примечание GHC: дескриптор Handle будет автоматически закрыт, когда сборщик мусора обнаружит, что он стал не ссылаться программой. Однако, полагаться на это поведение не рекомендуется: сборщик мусора непредсказуем. Если возможно, используйте явное hClose для закрытия Handle когда они больше не требуются. GHC в настоящее время не пытается освободить дескрипторы файлов, когда они закончились, вам нужно убедиться, что этого не происходит.
Стандартные дескрипторы
Три дескриптора выделены во время инициализации программы и изначально открыты.
Дескриптор, управляющий вводом из стандартного канала ввода Haskell-программы.
Дескриптор, управляющий выводом в стандартный канал вывода Haskell-программы.
Дескриптор, управляющий выводом в стандартный канал ошибок Haskell-программы.
Открытие и закрытие файлов
Открытие файлов
withFile :: FilePath -> IOMode -> (Handle -> IO r) -> IO r Source
withFile name mode act открывает файл, используя openFile и передает полученный дескриптор в вычисление act. Дескриптор будет закрыт при выходе из withFile, будь то нормальное завершение или возбуждение исключения. Если при закрытии дескриптора возникает исключение, то это исключение будет возбуждено withFile вместо любого исключения, возбуждённого act.
openFile :: FilePath -> IOMode -> IO Handle Source
Вычисление openFile file mode выделяет и возвращает новый открытый дескриптор для управления файлом file. Он управляет вводом, если mode равен ReadMode, выводом, если mode равен WriteMode или AppendMode, и вводом-выводом, если режим равен ReadWriteMode.
Если файл не существует и открывается для вывода, он должен быть создан как новый файл. Если mode равен WriteMode и файл уже существует, то он должен быть обнулен до нулевой длины. Некоторые операционные системы удаляют пустые файлы, поэтому нет гарантии, что файл будет существовать после openFile с mode WriteMode, если он не будет успешно записан впоследствии. Дескриптор размещается в конце файла, если mode равен AppendMode, и в начале в противном случае (в этом случае его внутреннее положение равно 0). Режим начального буфера зависит от реализации.
Эта операция может завершиться неудачно из-за:
-
isAlreadyInUseErrorесли файл уже открыт и не может быть повторно открыт; -
isDoesNotExistErrorесли файл не существует или (на системах POSIX) является FIFO без читателя иWriteModeбыл запрошен; или -
isPermissionErrorесли у пользователя нет разрешения на открытие файла.
Примечание: если вы будете работать с файлами, содержащими двоичные данные, вам следует использовать openBinaryFile.
См. openFile
Конструкторы
| ReadMode | |
| WriteMode | |
| AppendMode | |
| ReadWriteMode |
Примеры реализации
Определено в GHC.IO.IOMode Методыrange :: (IOMode, IOMode) -> [IOMode] Источник index :: (IOMode, IOMode) -> IOMode -> Int Источник unsafeIndex :: (IOMode, IOMode) -> IOMode -> Int Источник inRange :: (IOMode, IOMode) -> IOMode -> Bool Источник rangeSize :: (IOMode, IOMode) -> Int Источник unsafeRangeSize :: (IOMode, IOMode) -> Int Источник |
Закрытие файлов
hClose :: Handle -> IO () Источник
Вычисление hClose hdl делает дескриптор файла hdl закрытым. Перед завершением вычисления, если hdl является открытым для записи, его буфер сбрасывается как для hFlush. Выполнение hClose для дескриптора файла, который уже закрыт, не имеет эффекта; это не ошибка. Все другие операции с закрытым дескриптором файла завершатся с ошибкой. Если hClose завершается с ошибкой по любой причине, любые дальнейшие операции (кроме hClose) с дескриптором файла по-прежнему будут завершаться с ошибкой, как если бы hdl успешно закрылся.
Особые случаи
Эти функции также экспортируются модулем Prelude.
readFile :: FilePath -> IO String Источник
Функция readFile считывает файл и возвращает содержимое файла в виде строки. Файл считывается лениво, по запросу, как и с getContents.
writeFile :: FilePath -> String -> IO () Источник
Вычисление writeFile file str записывает строку str, в файл file.
appendFile :: FilePath -> String -> IO () Источник
Вычисление 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 Источник
Для дескриптора файла hdl, который подключен к физическому файлу, hFileSize hdl возвращает размер этого файла в байтах.
hSetFileSize :: Handle -> Integer -> IO () Источник
hSetFileSize hdl size обрезает физический файл с дескриптором hdl до size байтов.
Обнаружение конца входных данных
hIsEOF :: Handle -> IO Bool Источник
Для дескриптора файла для чтения hdl, hIsEOF hdl возвращает True, если нет дополнительных входных данных от hdl или для физического файла, если текущая позиция ввода/вывода равна длине файла. В противном случае возвращает False.
ПРИМЕЧАНИЕ: hIsEOF может заблокироваться, потому что ему необходимо попытаться прочитать из потока, чтобы определить, есть ли еще данные для чтения.
Вычисление isEOF идентично hIsEOF, за исключением того, что оно работает только с stdin.
Операции с буферами
data BufferMode Источник
Поддерживаются три типа буферизации: построчная, блочная или отсутствие буферизации. Эти режимы имеют следующие эффекты. Для вывода элементы записываются или сбрасываются из внутреннего буфера в соответствии с режимом буферизации:
-
построчная буферизация: весь буфер вывода сбрасывается всякий раз, когда выводится символ новой строки, буфер переполняется, вызывается
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
Примеры использования
| Eq HandlePosn | С версии: base-4.1.0.0 |
Определено в GHC.IO.Handle Методы(==) :: HandlePosn -> HandlePosn -> Bool Source (/=) :: HandlePosn -> HandlePosn -> Bool Source | |
| Show HandlePosn | С версии: base-4.1.0.0 |
Определено в GHC.IO.Handle МетодыshowsPrec :: Int -> HandlePosn -> ShowS Source show :: HandlePosn -> String Source showList :: [HandlePosn] -> ShowS Source | |
hSeek :: Handle -> SeekMode -> Integer -> IO () Source
Вычисление hSeek hdl mode i устанавливает позицию дескриптора hdl в зависимости от mode. Смещение i задается в байтах по 8 бит.
Если hdl является буферизованным по блокам или строкам, то перемещение к позиции, которая не находится в текущем буфере, сначала приведет к записи всех элементов в выходном буфере в устройство, а затем к сбросу входного буфера. Некоторые дескрипторы могут не поддерживать поиск (см. hIsSeekable), или поддерживать только подмножество возможных операций позиционирования (например, может быть возможен поиск только до конца ленты или к положительному смещению от начала или текущей позиции). Невозможно установить отрицательную позицию ввода-вывода или, для физического файла, позицию ввода-вывода за пределами текущего конца файла.
Данная операция может завершиться ошибкой:
-
isIllegalOperationErrorесли дескриптор не поддерживает поиск или не поддерживает запрошенный режим поиска. -
isPermissionErrorесли будет превышен системный лимит ресурсов.
Режим, определяющий влияние hSeek hdl mode i.
Конструкторы
| AbsoluteSeek | позиция |
| RelativeSeek | позиция |
| SeekFromEnd | позиция |
Примеры
Определено в GHC.IO.Device Методыrange :: (SeekMode, SeekMode) -> [SeekMode] Исходный код index :: (SeekMode, SeekMode) -> SeekMode -> Int Исходный код unsafeIndex :: (SeekMode, SeekMode) -> SeekMode -> Int Исходный код inRange :: (SeekMode, SeekMode) -> SeekMode -> Bool Исходный код rangeSize :: (SeekMode, SeekMode) -> Int Исходный код unsafeRangeSize :: (SeekMode, SeekMode) -> Int Исходный код |
hTell :: Handle -> IO Integer Исходный код
Вычисление hTell hdl возвращает текущую позицию дескриптора hdl, как количество байтов с начала файла. Возвращённое значение может быть далее передано в hSeek для перемещения дескриптора в текущую позицию.
Данная операция может завершиться ошибкой:
-
isIllegalOperationErrorесли дескриптор не поддерживает позиционирование.
Свойства дескриптора
hIsOpen :: Handle -> IO Bool Исходный код
hIsClosed :: Handle -> IO Bool Исходный код
hIsReadable :: Handle -> IO Bool Исходный код
hIsWritable :: Handle -> IO Bool Исходный код
hIsSeekable :: Handle -> IO Bool Исходный код
Операции с терминалом (не переносимо: только GHC)
hIsTerminalDevice :: Handle -> IO Bool Исходный код
Подключен ли дескриптор к терминалу?
hSetEcho :: Handle -> Bool -> IO () Исходный код
Установить состояние отображения ввода с терминала.
hGetEcho :: Handle -> IO Bool Исходный код
Получить состояние отображения ввода с терминала.
Отображение состояния дескриптора (не переносимо: только GHC)
hShow :: Handle -> IO String Исходный код
hShow находится в монаде IO и даёт более подробный вывод, чем (чистый) экземпляр Show для Handle.
Ввод и вывод текста
Ввод текста
hWaitForInput :: Handle -> Int -> IO Bool Исходный код
Вычисление 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 Исходный код
Вычисление hReady hdl показывает, доступен ли хотя бы один элемент для чтения с дескриптора hdl.
Данная операция может завершиться ошибкой:
-
isEOFErrorесли достигнут конец файла.
hGetChar :: Handle -> IO Char Исходный код
Вычисление hGetChar hdl считывает символ из файла или канала, управляемого hdl, блокируя до тех пор, пока символ не станет доступным.
Данная операция может завершиться ошибкой:
-
isEOFErrorесли достигнут конец файла.
hGetLine :: Handle -> IO String Исходный код
Вычисление 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 целых чисел и их степеней двойки можно написать так:
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, которая используется для декодирования байтов в символы Юникода при чтении и кодирования символов Юникода в байты при записи.
Кодировка по умолчанию 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 — это спецификация схемы преобразования между последовательностями байтов и последовательностями символов Юникода.
Например, UTF-8 — это кодировка символов Юникода в последовательность байтов. TextEncoding для UTF-8 — это utf8.
Экземпляры
| Show TextEncoding | Since: base-4.3.0.0 |
Определено в GHC.IO.Encoding.Types МетодыshowsPrec :: Int -> TextEncoding -> ShowS Source show :: TextEncoding -> String Source showList :: [TextEncoding] -> ShowS Source | |
Кодировка Latin1 (ISO8859-1). Эта кодировка напрямую сопоставляет байты с первыми 256 кодовыми точками Юникода и, таким образом, не является полной кодировкой Юникода. Попытка записать символ больше, чем '\255', в Handle с использованием кодировки latin1 приведет к ошибке.
Юникод-кодировка UTF-8
utf8_bom :: TextEncoding Source
Юникод-кодировка UTF-8 с меткой порядка байтов (BOM; последовательность байтов 0xEF 0xBB 0xBF). Эта кодировка ведет себя как utf8, за исключением того, что на входе последовательность BOM игнорируется в начале потока, а на выходе последовательность BOM добавляется в начало.
Метка порядка байтов строго говоря не нужна в UTF-8, но иногда используется для идентификации кодировки файла.
Юникод-кодировка UTF-16 (следует использовать метку порядка байтов для указания порядка байтов).
utf16le :: TextEncoding Source
Юникод-кодировка UTF-16 (little-endian)
utf16be :: TextEncoding Source
Юникод-кодировка UTF-16 (big-endian)
Юникод-кодировка UTF-32 (следует использовать метку порядка байтов для указания порядка байтов).
utf32le :: TextEncoding Source
Юникод-кодировка UTF-32 (little-endian)
utf32be :: TextEncoding Source
Юникод-кодировка UTF-32 (big-endian)
localeEncoding :: TextEncoding Source
Юникод-кодировка текущей локали
Это начальная кодировка локали: если она была впоследствии изменена с помощью setLocaleEncoding, это значение не будет отражать это изменение.
Кодировка, в которой кодовые точки Юникода преобразуются в байты путем взятия кодовой точки по модулю 256. При декодировании байты напрямую преобразуются в эквивалентную кодовую точку.
Эта кодировка никогда не приводит к ошибкам ни в одном направлении. Однако кодирование отбрасывает информацию, поэтому кодирование, за которым следует декодирование, не является тождественным преобразованием.
Since: base-4.4.0.0
mkTextEncoding :: String -> IO TextEncoding Source
Ищет именованную кодировку Юникода. Может завершиться ошибкой с
-
isDoesNotExistErrorесли кодировка неизвестна
Набор известных кодировок зависит от системы, но включает по крайней мере:
UTF-8
-
UTF-16,UTF-16BE,UTF-16LE -
UTF-32,UTF-32BE,UTF-32LE
Существует дополнительная нотация (заимствованная у GNU iconv) для указания того, как обрабатываются недопустимые символы:
- суффикс
//IGNORE, напримерUTF-8//IGNORE, приведет к тому, что все недопустимые последовательности на входе будут игнорироваться, а на выходе будут отбрасываться все кодовые точки, которые не имеют представления в целевой кодировке. - суффикс
//TRANSLITвыберет символ замены для недопустимых последовательностей или кодовых точек. - суффикс
//ROUNDTRIPбудет использовать механизм экранирования в стиле PEP383 для представления любых недопустимых байтов на входе как кодовых точек Юникода (в частности, как одиночные суррогаты, которые обычно являются недопустимыми в UTF-32). На выходе эти специальные кодовые точки обнаруживаются и преобразуются обратно в соответствующие исходные байты.
В теории, этот механизм позволяет произвольным данным передаваться через String без потери данных. На практике существуют два ограничения, о которых следует помнить:
- Это может сработать только для кодировки, являющейся надмножеством ASCII, поскольку по соображениям безопасности мы отказываемся экранировать байты меньше 128. Многие интересующие нас кодировки являются надмножествами ASCII (в частности, можно предположить, что кодировка локали является надмножеством ASCII), но многие (такие как UTF-16) — нет.
- Если используемая кодировка сама по себе не является обратимой, этот механизм может дать сбой. Обратимые кодировки — это те, которые имеют инъективное отображение в Unicode. Почти все кодировки соответствуют этому критерию, но некоторые нет. В частности, Shift-JIS (CP932) и Big5 содержат несколько разных кодировок одной и той же кодовой точки Unicode.
В 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 () Source
Устанавливает NewlineMode для указанного Handle. Сначала очищаются все буферизованные данные.
Представление символа перевода строки во внешнем файле или потоке.
Экземпляры
| Eq Newline | Since: base-4.2.0.0 |
| Ord Newline | Since: base-4.3.0.0 |
| Read Newline | Since: base-4.3.0.0 |
| Show Newline | Since: base-4.3.0.0 |
nativeNewline :: Newline Source
Нативное представление символа перевода строки для текущей платформы: LF в системах Unix, CRLF в Windows.
data NewlineMode Source
Задает преобразование, если таковое имеется, символов новой строки между внутренними строками и внешним файлом или потоком. Предполагается, что строки Haskell представляют новые строки с помощью символа '\n'; режим новой строки указывает, как преобразовывать '\n' при выводе и что преобразовывать в '\n' при вводе.
Краткое описание конструкторов
| NewlineMode | |
Instances
noNewlineTranslation :: NewlineMode Source
Не производить никакого преобразования новой строки.
noNewlineTranslation = NewlineMode { inputNL = LF, outputNL = LF }
universalNewlineMode :: NewlineMode Source
Сопоставлять '\r\n' с '\n' на входе и '\n' с собственным представлением новой строки на выходе. Этот режим можно использовать на любой платформе, и он работает с текстовыми файлами, использующими любую соглашение о новой строке. Недостатком является то, что readFile >>= writeFile может привести к другому файлу.
universalNewlineMode = NewlineMode { inputNL = CRLF,
outputNL = nativeNewline }
nativeNewlineMode :: NewlineMode Source
Использовать собственное представление новой строки как на входе, так и на выходе.
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/8.10.2/docs/html/libraries/base-4.14.1.0/System-IO.html