Запись в файл в потоковом режиме и остановка при достижении заданного размера файла памяти

Допустим, я хочу сохранить поток MyItem в файл (например, в JSON). Я хотел бы остановиться, когда файл достигает определенного предела размера в байтах. Я хотел бы сделать это в Haskell... потоковая передача для меня не проблема, а как получить информацию о размере файла после каждого элемента, помещенного в этот файл...


person Nicolas Henin    schedule 10.04.2020    source источник
comment
Что-то не так с использованием hTell ? или hFileSize из того же модуля System.IO?   -  person jpmarinier    schedule 10.04.2020
comment
Могут ли значения json быть разделены и охватывать более одного файла? Является ли ограничение по размеру жестким ограничением или его можно превысить, чтобы уместить последний MyItem в файле?   -  person danidiaz    schedule 10.04.2020
comment
@jpmarinier, я не знаю, что тогда было нужно Николя, но одна проблема заключается в том, что hTell работает только для доступных для поиска дескрипторов (фактических файлов, блочных устройств и т. д.). Если требования меняются и файл иногда оказывается каналом (или каким-то другим дескриптором), тогда весь код нужно будет переписать.   -  person dfeuer    schedule 22.02.2021
comment
@dfeuer - Действительно, в то время я не рассматривал такую ​​​​возможность, учитывая, что Николя упомянул файл. В системах Linux базовый системный вызов lseek может возвращать ESPIPE, если по какой-то причине (реализации) поток не поддерживает правильное смещение. В этом случае я бы сказал, что наименее плохой вариант, вероятно, состоит в том, чтобы логика программы выполняла подсчет, возможно, используя некоторую объектную оболочку вокруг дескриптора файла на уровне ОС.   -  person jpmarinier    schedule 22.02.2021


Ответы (1)


Я не думаю pipes что-то для этого из коробки, но легко написать свой собственный toHandleBounded.

На каждом шаге вы проверяете размер файла и, если он меньше ограничения, которое вы выполняете, записываете в файл еще один блок.

toHandleBounded :: MonadIO m => Integer -> Handle -> Consumer' ByteString m ()
toHandleBounded limit hd = do
  current <- liftIO $ hTell hd
  when (current < limit) $ do
    x <- await
    liftIO $ hPut hd x
    toHandleBounded limit hd

main :: IO ()
main =
  withFile "/dev/urandom" ReadMode $ \hIn ->
  withFile "out.txt" WriteMode $ \hOut ->
    runEffect $ P.fromHandle hIn >-> toHandleBounded (1024 * 500 ) hOut
person Masse    schedule 22.02.2021