чтение из файла построчно (мало памяти) в Common Lisp - PullRequest
0 голосов
/ 29 ноября 2018

Я ищу способ чтения из нескольких файлов по 1 s-выражению (список данных) за раз.

Дело в том, что файлы огромны - сотни мегабайт или гигабайт.И мне нужна оперативная память для вычислений.

Для выходных файлов

(defun add-to-file (process-result file-path)
  (with-open-file (os file-path :direction :output
                                :if-exists :append
                                :if-does-not-exist :create)
    (print process-result os)))

хорошо справляется с построчным добавлением строки результата или s-выражения.(Я не знаю - может быть, это не самый эффективный способ?).

Некоторое время назад я попросил макрос, который открывает столько файлов, сколько я хочу с with-open-file и где я могу получить доступиз тела все файлы, чьи переменные потока я мог бы создать и передать.Однако, поскольку число открытых входных и выходных файлов варьируется, возможно, дизайнеру гораздо проще вызывать каждый файл с такими вызывающими программами - открывать их - переходить в нужную позицию - писать или читать - и затем снова закрывать егоПодумал я.

Для вывода данная функция выполняет свою работу.Однако для ввода мне бы хотелось иметь функцию, которая каждый раз, когда я ее вызываю, читает следующее lisp-выражение (s-выражение) и имеет вид памяти, где он читает последний раз в файле, и каждый раз, когда я его вызываю- открывает файл заново и знает, где его прочитать - и возвращает значение - и в следующий раз читает и возвращает следующее значение и т. д. Аналогично генераторам Python через итераторы - которые выдают следующее значение в последовательности.

Я хочу обработать - прочитанное - выражение файла по выражению - чтобы использовать минимальное количество памяти.

Как бы вы атаковали такую ​​задачу?Или у вас на уме хорошая стратегия?

1 Ответ

0 голосов
/ 29 ноября 2018

Эскиз:

создание структуры или класса, в котором хранится последняя прочитанная позиция.

(defstruct myfile
  path
  (last-position 0))

(defmethod next-expression ((mf myfile))
  (with-open-file (s (myfile-path mf) :direction :input)
    (file-position s (myfile-last-position mf))
    (prog1
        (read s)
      (setf (myfile-last-position mf) (file-position s))))) 

Пример использования:

(defparameter *mf1* (make-myfile :path (pathname "/foo/bar.sexp")))

(print (next-expression *mf1*)) ;; get first s-expr from file
;; do sth else
(myfile-last-position *mf1*)  ;; check current position
;; do sth else
(print (next-expression *mf1*)) ;; gives next s-expr from file

Затем напишите метод дляпроверить, доступно ли новое s-выражение.И т.д.

...