file-io - 到达eof时,读取行在Lisp中如何工作?

标签 file-io lisp common-lisp

上下文: 我有一个名为 fr.txt 的文本文件其中包含 3 列文本:

65  A   #\A
97  a   #\a
192     À   #\latin_capital_letter_a_with_grave
224     à   #\latin_small_letter_a_with_grave
etc...

我想创建一个函数来读取第一列(最终也是第三列)并将其写入另一个名为 alphabet_code.txt 的文本文件中.

到目前为止我有这个功能:

(defun alphabets()
   (setq source (open "fr.txt" :direction :input :if-does-not-exist :error))
   (setq code (open "alphabet_code.txt" :direction :output :if-does-not-exist :create :if-exists :supersede))
   (loop
      (setq ligne (read-line source nil nil))
      (cond
         ((equal ligne nil) (return))
         (t (print (read-from-string ligne) code))
      )
   )
   (close code)
   (close source)
)

我的问题:

  1. 我不太明白read-line函数的参数是怎么来的。我读过this doc ,但它对我来说仍然很模糊。如果有人有非常简单的示例,那将会有所帮助。

  2. 使用当前代码,我得到这个错误:*** - read: input stream #<input string-input-stream> has reached its end即使我改变了 nil nil(read-line source nil nil)其他值。

感谢您的宝贵时间!

最佳答案

您的问题

read-line 可选参数

read-line接受 3 个可选参数:

  1. eof-error-p:在 EOF 上做什么(默认:错误)
  2. eof-value:看到 EOF 时返回什么而不是错误
  3. recursive-p:你是从你的 print-object 调用它吗?方法(暂时忘掉这个)

例如,当 stream 处于 EOF 时,

  • (read-line stream) 将发出 end-of-file 信号错误
  • (read-line stream nil) 将返回 nil
  • (read-line stream nil 42) 将返回 42

请注意,(read-line stream nil)(read-line stream nil nil) 相同,但人们通常仍显式传递第二个可选参数。 nileof-value 适用于 read-line 因为 nil 不是字符串并且 read -line 只返回字符串。

另请注意,在 read 的情况下第二个可选参数通常是 stream 本身:(read stream nil stream)。很方便。

错误

您收到来自 read-from-string 的错误, 不是 read-line ,因为很明显,您的文件中有一个空行。

我知道是因为错误提到了 string-input-stream , 不是 file-stream .

你的代码

您的代码在功能上是正确的,但在风格上却大错特错。

  1. 你应该使用with-open-file只要有可能。
  2. 你不应该使用 print在代码中,它是一个奇怪的遗留函数,主要用于交互使用。
  3. 不能用setq 创建局部变量- 使用 let或其他等效形式(在这种情况下,您永远不需要 let!:-)

以下是我将如何重写您的函数:

(defun alphabets (input-file output-file)
  (with-open-stream (source input-file)
    (with-open-stream (code output-file :direction :output :if-exists :supersede)
      (loop for line = (read-line source nil nil)
          as num = (parse-integer line :junk-allowed t)
        while line do
          (when num
            (write num :stream code)
            (write-char #\Newline code))))))
(alphabets "fr.txt" "alphabet_code.txt")

查看文档:

  1. loop : for/as , while , do
  2. write , write-char
  3. parse-integer

或者,我可以使用相应的 loop conditional 而不是 (when num ...) .

此外,我可以编写 (format code "~D~%"num) 而不是 write+write-char

请注意,我没有传递那些与默认值相同的with-open-stream 参数。 默认设置是一成不变的,您编写的代码和用户阅读的代码越少,出错的可能性就越小。

关于file-io - 到达eof时,读取行在Lisp中如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42102947/

相关文章:

clojure - Clojure、Scheme/Racket 和 Common Lisp 之间有什么区别?

common-lisp - Common Lisp 符号中允许使用哪些字符?

C++ - 访问可执行文件上的 "dropped"文件

list - 获取列表中的第 N 个元素作为列表而不是 LISP 中的数字?

lisp - 对称二维数组

loops - 使用 lisp 循环宏进行高级循环

scheme - 使用方案中的字符串获取变量值

java - 使用 J2ME 在手机内存中写入文件

linux - Strace——打印内容而不是地址

java - 尝试将一个类中的信息刷新到java中的另一个类中