2

我正在尝试将所有子目录的列表写入文件,但子目录名称中的 unicode 符号被问号替换。我在 Windows XP 上使用 CLISP 2.49。

这是代码的简短版本:

(let ((*pathname-encoding* (ext:make-encoding :charset 'charset:utf-8
                                              :line-terminator :dos)))
    (with-open-file (stream "folders.txt"
                     :direction :output
                     :if-exists :overwrite
                     :if-does-not-exist :create
                     :external-format (ext:make-encoding :charset 'charset:utf-8
                                                         :line-terminator :dos))
       (format stream "~A~&" (directory ".\\*\\"))))
4

1 回答 1

2

你做错了什么

您应该知道这*pathname-encoding*是一个SYMBOL-MACRO,而不是一个变量。正如CLISP手册中的注释所说,

提醒:您必须对SYMBOL-MACRO使用EXT:LEETF/EXT:LETF*LET/LET*将不起作用!

所以,你需要做的是

(ext:letf ((*pathname-encoding* charset:utf-8)) ...)

(无论如何都会忽略line-terminator模式*pathname-encoding*)。

例子

$ touch 'идиотский файл'
$ ls
идиотский файл
$ LANG=C ls
?????????????????? ????????
$ LANG=C clisp -q -norc 
> *pathname-encoding* 
#<ENCODING CHARSET:ASCII :UNIX>
> *default-file-encoding* 
#<ENCODING CHARSET:ASCII :UNIX>
> *terminal-encoding* 
#<ENCODING CHARSET:ASCII :UNIX>
> (letf ((*pathname-encoding* charset:utf-8))
    (with-open-file (o "foo" :direction :output :external-format charset:utf-8) 
      (format o "~A~%" (directory "*"))))
NIL
> (quit)
$ cat foo
(/home/sds/tmp/z/идиотский файл /home/sds/tmp/z/foo)

调试您的特定问题

在任何情况下,CLISP 都不会打印或返回?它无法处理的字符 - 它会发出错误信号(尝试省略其中一个编码规范,您将得到一个错误Invalid byte #xD0 in CHARSET:ASCII conversion- fromwrite或 from directory)。

因此问题出在边界上:

  • 要么操作系统给出 CLISP 问号而不是 unicode(因为它认为 CLISP 无法处理 i18n)
  • 或者 CLISP 生成的文件被低级 OS 层错误地保存
  • 或者您用于查看文件的工具无法显示 unicode 字符

(只有最后一个选项似乎是合理的)。

你可以做的是:

  1. 从删除编码规范开始 - 你得到转换错误吗?检查默认的编码位置*pathname-encoding*(对于像&c这样的符号宏来说,这是花哨的 Lisp 词)
  2. 确保*pathname-encoding*utf-8并尝试类似的东西(coerce (pathname-name (car (directory "*"))) 'list)- 在我上面的例子中我看到了(#\CYRILLIC_SMALL_LETTER_I ...);您是否像我一样看到 unicode 字符,或者您看到了#\?吗?
  3. 试试cygwin( ls, ls | od, ls > foo; cat foo | od) 看看它是否可以捕获非 ASCII 字符。
于 2013-04-24T13:22:19.673 回答