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

时间:2014-01-04 21:05:11

标签: file-io lisp common-lisp

我有一个.dat文件,里面有一些数据(文本,数字等)。该数据文件的结构采用信息块的形式,以包含短语“patch n”的行开头,其中n是块的编号:

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

现在,我想重新排列块并将它们以新的顺序(与补丁号一起)写入另一个文件。此新订单在new-order = (3 1 0 2)等列表中定义。此外,每个块的第一行(在初始文件中)的行号在诸如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)))))))

这显然不是一种有效的方式,我想知道导致这个问题的原因是什么,最好的方法是什么?

1 个答案:

答案 0 :(得分:2)

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

侧面提示:使用dolist代替dotimesnth构建。

如果您不想让 n 传递( n 是补丁的数量),并且您无法将所有内容保存在内存中,则可以编写补丁到临时文件,然后以所需的顺序连接它们。如果您还没有足够的磁盘空间,那么它就会成为一个就地排序问题,并且元素大小会有所不同,这需要更多一些。