输入流在对象内结束

时间:2012-11-15 10:57:19

标签: input stream lisp common-lisp

我想计算平面文件中的行数,所以我编写了代码:

(defun ff-rows (dir file)
  (with-open-file (str (make-pathname :name file
                                      :directory dir)
                                      :direction :input)
    (let ((rownum 0))
      (do ((line (read-line str file nil 'eof)
                 (read-line str file nil 'eof)))
          ((eql line 'eof) rownum)
        (incf rownum )))))

然而我收到错误:

*** - READ: input stream
       #<INPUT BUFFERED FILE-STREAM CHARACTER #P"/home/lambda/Documents/flatfile"
         @4>
      ends within an object

请问这里有什么问题?我试过计算行数;这个操作很好。

注意:这是我用来测试函数的平面文件的内容:

2 3 4 6 2 
1 2 3 1 2
2 3 4 1 6

3 个答案:

答案 0 :(得分:4)

据我所知,问题是你的(读行......)电话中的“文件”。

根据hyperspec,读取线的签名是:

read-line &optional input-stream eof-error-p eof-value recursive-p
=> line, missing-newline-p

...这意味着“file”被解释为eof-error-p,nil被解释为eof-value而'eof被解释为recursive-p。不用说,问题随之而来。如果从读取线调用中删除“文件”(例如(read-line str nil :eof)),则代码运行正常,无需在我的机器上进行进一步修改(AllegroCL&amp; LispWorks)。

答案 1 :(得分:4)

有点短。

(defun ff-rows (dir file)
  (with-open-file (stream (make-pathname :name file
                                         :directory dir)
                          :direction :input)
    (loop for line = (read-line stream nil nil)
          while line count line)))

请注意,您需要正确获取READ-LINE的参数。首先是流。文件不是参数列表的一部分。

将路径名处理混合到一般的Lisp函数中通常也不是一个好主意。

(defun ff-rows (pathname)
  (with-open-file (stream pathname :direction :input)
    (loop for line = (read-line stream nil nil)
          while line count line)))

在另一个函数或其他代码中处理路径名。将路径名组件传递给函数通常是错误的设计。传递完整的路径名。

使用LispWorks文件选择器:

CL-USER 2 > (ff-rows (capi:prompt-for-file "some file"))
27955

更好的是所有基本I / O函数都在流上工作,而不是路径名。因此,您可以计算网络流,串行线或其他流中的行。

答案 2 :(得分:1)

(defun ff-rows (dir file)
  (with-open-file
      (str (make-pathname :name file :directory dir)
           :direction :input)
    (let ((result 0))
      (handler-case
          (loop (progn (incf result) (read-line str)))
        (end-of-file () (1- result))
        (error () result)))))

现在,当然,如果你比我更迂腐,你可以指定你想要处理的错误类型,但是对于这个简单的例子,这将会做。

编辑:我认为@Moritz更好地回答了这个问题,但这可能是一个如何使用read-line引发的错误而不是试图避免错误的示例。