file-io - 将数据文件的一部分写入(并重新排列)到另一个文件

标签 file-io lisp common-lisp

我有一个 .dat 文件,其中包含某些数据(文本、数字等)。这个数据文件的结构是信息 block 的形式,它以包含短语“patch n”的行开头,n 是 block 的编号:

patch 0
-----
-----
patch 1
-----
-----
-----
.
.
patch 3
-----

现在,我想重新排列 block 并以新顺序(根据补丁号)将它们写入另一个文件。这个新订单在列表中定义,例如 new-order = (3 1 0 2)。此外,每个 block (在初始文件中)的第一行的行号在列表中定义,例如 line-numbers = (0 24 134 210 520)

我的问题是用 common-lisp 编写代码的好方法。我写了下面的代码,但是在一些数据被写入新文件之后,显然这个过程陷入了一个无限循环,我不得不在没有得到结果的情况下停止自己:

(with-open-file (out output-stream
                     :direction :output
                     :if-exists :new-version
                     :if-does-not-exist :create)
  (with-open-file (in input-stream
                      :direction :input
                      :if-does-not-exist nil)
    (let ((new-order (list 3 1 0 2)))
      (dotimes (n (length new-order))
        (loop for line = (read-line in nil 'eof)
              for i from 1
              do (when (<= (nth (nth n new-order) line-numbers)
                           i
                           (nth (1+ (nth n new-order)) line-numbers))
                   (format out "~a~%" line)))))))

这显然不是一种有效的方法,我想知道是什么导致了这个问题,什么是解决这个问题的最佳方法?

最佳答案

主要问题似乎是您需要在每次通过后重置文件位置。无限循环的发生是因为您从不检查文件结尾(并抑制了信号)。

侧面提示:使用 dolist 而不是 dotimesnth 构造。

如果您不想进行 n 遍(n 是补丁的数量),并且您不能将全部内容保存在内存中,您可以编写补丁到临时文件,然后按所需顺序连接它们。如果您也没有足够的磁盘空间,它将变成一个具有不同元素大小的就地排序问题,这会涉及更多一些。

关于file-io - 将数据文件的一部分写入(并重新排列)到另一个文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20926741/

相关文章:

java - 如何从solr/data/index读取数据

return - 如何跳出 Lisp 中的函数?

common-lisp - 如何访问元对象/槽定义槽?为什么 slot-value 可以访问对象的槽,但不能访问元对象的槽?

java - 需要以管理员身份运行 Java 应用程序吗?

java - 从定义位置的字符串变量获取引用

c - 字符数组在文件处理中不起作用

list - elisp 如何将 lambda 应用于列表?

list - 有没有办法就地提取列表的所有元素

lisp - 如何从嵌套列表 lisp 中删除元素

lisp - Allegro CL Free Express Edition 9.0 中函数定义应该写在哪里?