Common Lisp读取含非ASCII字符文件时末尾出现空字符问题求助
解决Common Lisp读取UTF-8文件时字符串末尾出现空字符的问题
你的函数目前有两个核心问题导致非ASCII字符读取后出现空字符(^@,即#\Null),我们一步步来修正:
1. 先修正with-open-file的语法错误
你原来的代码里,:external-format 'utf-8的位置完全错了——它必须作为with-open-file的关键字参数放在(stream path)的括号内,而不是单独放在函数体外面。错误的写法会导致这个编码设置根本不生效,函数会使用默认编码读取文件,这本身就会引发非ASCII字符的读取异常。
2. 错误地用文件字节数作为字符串长度
file-length返回的是文件的字节数,但UTF-8编码中,非ASCII字符(比如特殊符号、非英文字符)会占用2-4个字节,而每个这样的字符在Common Lisp中是一个独立的字符对象。你用字节数创建字符串,再用read-sequence读取字符,最终读取的字符数会比字符串长度少,剩下的位置自然会被填充为空字符。
正确的实现方式
我们可以通过循环读取所有字符直到文件末尾,或者用with-output-to-string更简洁地收集所有字符,彻底避免预先计算长度的问题:
(defun file-to-str (path) (with-open-file (stream path :external-format 'utf-8) (with-output-to-string (output) (loop for char = (read-char stream nil nil) while char do (write-char char output)))))
如果你使用ASDF(大多数Common Lisp环境默认包含),还可以直接用uiop库提供的成熟函数,它已经处理了所有边缘情况:
(uiop:read-file-string path :external-format :utf-8)
验证你的测试案例
当你执行echo "~a^?" > ~/teste(假设^?是一个非ASCII字符),用修正后的函数读取该文件时,会正确获取所有字符,不会在末尾出现空字符。
内容的提问来源于stack exchange,提问作者Parjánya
相关产品推荐
相关产品推荐

