我收到了一个包含未知字符编码的文件。正在运行file -bi test.trace
会返回text/plain; charset=us-ascii
但使用
(with-open-file (stream "/home/*/test.trace" :external-format :us-ascii)
(code-to-work-with-file))
给了我一个例外:
:ASCII stream decoding error on
#<SB-SYS:FD-STREAM for "file /home/*/test.trace" {10208D2723}>:
the octet sequence #(194) cannot be decoded. [Condition of type SB-INT:STREAM-DECODING-ERROR]
如何在打开文件之前检测文件的编码?
我可以使用emacs
,less
和nano
打开文件,因为它似乎是对编码的错误检测或file
的差异并且sbcl
认为编码应该是这样的。
我目前通过强制每个文件使用vim +set nobomb | set fenc=utf8| x file-path
进行utf8编码来避免此问题。但即便在此file
仍然认为它是us-ascii编码之后。另外,这不是一个有效的永久解决方案,而是一个让它工作的肮脏黑客。
答案 0 :(得分:1)
正如here中的prorgammers stackexchange指出的那样,
文件通常用文件头指示它们的编码。有 这里有很多例子。然而,即使阅读标题,你也永远不会 确定文件的编码实际使用的是什么。
我在我的系统中查找了跟踪文件并找到了这个,但这没有任何有趣的东西
2016-06-22 13:10:07☆| ruby-2.2.3@laguna | Antonios-MacBook-Pro在〜/ learn / lisp / stackoverflow / scripts中 ○→文件-I resources / hello.trace resources / hello.trace:text / plain;字符集= US-ASCII
2016-06-22 13:11:50☆| ruby-2.2.3@laguna | Antonios-MacBook-Pro在〜/ learn / lisp / stackoverflow / scripts中 ○→cat资源/ hello.trace 调用println! {&#34;你好,世界!&#34; } 打印! {concat! (&#34;你好,世界!&#34;,&#34; \ n&#34;)}
所以使用这段代码,我可以读到它:
CL-USER> (with-open-file (in "/Users/toni/learn/lisp/stackoverflow/scripts/resources/hello.trace" :external-format :us-ascii)
(when in
(loop for line = (read-line in nil)
while line do (format t "~a~%" line))))
println! { "Hello, World!" }
print! { concat ! ( "Hello, World!" , "\n" ) }
NIL
甚至用中文或其他任何东西:
我们可以像这样阅读ascci字符
CL-USER> (format nil "~{~C~}" (mapcar #'code-char '(194)))
"Â"
或任何其他奇怪的角色,所以似乎可以是带有重音的字符我将其添加到文件中:
println! { "Hello, World!" }
print! { concat ! ( "Hello, World!" , "\n" ) }
Â
patatopita
我得到同样的错误:
:
上的ASCII流解码错误for&#34; file /Users/toni/learn/lisp/stackoverflow/scripts/resources/hello.trace" {1003994043}&GT;:
八位字节序列#(195)无法解码。 [SB-INT型的条件:STREAM-DECODING-ERROR]
所以此时你可以使用续约和重新启动,更改字符,有一个选项,我不是这类代码的专家,但可能会重新启动
Restarts:
0: [ATTEMPT-RESYNC] Attempt to resync the stream at a character boundary and continue.
1: [FORCE-END-OF-FILE] Force an end of file.
2: [INPUT-REPLACEMENT] Use string as replacement input, attempt to resync at a character boundary and continue.
3: [*ABORT] Return to SLIME's top level.
4: [ABORT] abort thread (#<THREAD "repl-thread" RUNNING {10050E0003}>)
输入替换,如果没有像拉丁语1或ISO那样尝试欧洲......
CL-USER> (with-open-file (in "/Users/toni/learn/lisp/stackoverflow/scripts/resources/hello.trace" :external-format :latin-1)
(when in
(loop for line = (read-line in nil)
while line do (format t "~a~%" line))))
println! { "Hello, World!" }
print! { concat ! ( "Hello, World!" , "\n" ) }
¬
patatopita
NIL
它应该有效,祝你好运
所以让我们阅读欧洲字符集