首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >只有在提示符下执行时才会出现sbcl编码错误?

只有在提示符下执行时才会出现sbcl编码错误?
EN

Stack Overflow用户
提问于 2013-07-16 07:00:27
回答 1查看 617关注 0票数 5

我有一段代码,如果从emacs内部的slime提示符执行,则运行时不会出现错误。如果我从提示符启动sbcl,我会得到错误:

代码语言:javascript
复制
* (ei:proc-file "BRAvESP000.log" "lixo")

debugger invoked on a SB-INT:STREAM-ENCODING-ERROR:
  :UTF-8 stream encoding error on
  #<SB-SYS:FD-STREAM for "file /Users/arademaker/work/IBM/scolapp/lixo"
    {10049E8FF3}>:

    the character with code 55357 cannot be encoded.

Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):
  0: [OUTPUT-NOTHING    ] Skip output of this character.
  1: [OUTPUT-REPLACEMENT] Output replacement string.
  2: [ABORT             ] Exit debugger, returning to top level.

(SB-IMPL::STREAM-ENCODING-ERROR-AND-HANDLE #<SB-SYS:FD-STREAM for "file /Users/arademaker/work/IBM/scolapp/lixo" {10049E8FF3}> 55357)
0]

令人费解的是,在这两种情况下,我都使用相同的sbcl 1.1.8和相同的机器,即MacOS10.8.4。有什么想法吗?

代码:

代码语言:javascript
复制
(defun proc-file (filein fileout &key (fn-convert #'identity))
  (with-open-file (fout fileout
                   :direction :output
                   :if-exists :supersede
                   :external-format :utf8)
    (with-open-file (fin filein :external-format :utf8)
      (loop for line = (read-line fin nil)
        while line
        do 
        (handler-case
        (let* ((line (ppcre:regex-replace "^.*{jsonTweet=" line "{\"jsonTweet\":"))
               (data (gethash "jsonTweet" (yason:parse line))))
          (yason:encode (funcall fn-convert (yason:parse data)) fout)
          (format fout "~%"))
          (end-of-file ()
        (format *standard-output* "Error[~a]: ~a~%" filein line)))))))
EN

回答 1

Stack Overflow用户

发布于 2013-12-06 03:17:16

这几乎可以肯定是yason中的一个bug。JSON要求,如果非BMP字符被转义,则通过代理项对进行转义。下面是一个使用U+10000的简单示例(它在json中可选地转义为“\ud800udc00”;我使用babel是因为babel的转换更少):

代码语言:javascript
复制
(map 'list #'char-code (yason:parse "\"\\ud800\\udc00\"")) 
  => (55296 56320)

unicode代码点55296 (十进制)是代理项对的开始,除非在UTF-16中作为代理项对出现,否则不应出现。幸运的是,可以通过使用babel将字符串编码为UTF-16然后再编码回来,轻松地解决这个问题:

代码语言:javascript
复制
(babel:octets-to-string (babel:string-to-octets (yason:parse "\"\\ud800\\udc00\"") :encoding :utf-16le) :encoding :utf-16le)
  => ""

您应该能够通过更改以下行来解决此问题:

代码语言:javascript
复制
(yason:encode (funcall fn-convert (yason:parse data)) fout)

若要使用中间字符串,请将其转换为UTF-16,然后再转换回来。

代码语言:javascript
复制
(write-sequence
 (babel:octets-to-string
  (babel:string-to-octets
   (with-output-to-string (outs)
    (yason:encode (funcall fn-convert (yason:parse data)) outs))
   :encoding :utf-16le)
  :encoding :utf-16le)
 fout)

我提交了一个补丁,这个补丁已经被接受来修复yason的这个问题:

https://github.com/hanshuebner/yason/commit/4a9bdaae652b7ceea79984e0349a992a5458a0dc

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17665322

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档