2013-07-15 21 views
5

emacs内のslimeプロンプトから実行した場合、エラーなしで実行するコードがあります。私はプロンプトからSBCL開始した場合、私はエラーを得た:プロンプトから実行した場合のみ、sbclエンコーディングエラーが発生しますか?

* (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と同じマシンはMac OS 10.8.4を使用していますということです。何か案が?

コード:

(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))))))) 
+1

私はあなたがこれを仮定することによって開始することを示唆しているが、yasonの問題ではありません。

(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でこれを修正するために承認されたパッチを提出しましたもしあれば素早く - あなたのコードに '(format * standard-output *"〜&〜{〜x〜^〜) "(map 'list' char-code line))'を追加してください。失敗したケースの最終行は、SLIME環境の対応する行と同じですか? –

+1

複数のディレクトリにBRAvESP000.logという名前のファイルがあり、SLIMEまたは手動でSBCLを起動している場合は、現在のディレクトリが異なります。絶対パスを試してください。 – acelent

+0

文字コードが間違いでない場合は、サロゲートペアのUnicode範囲に属します。これらはUTF-8エンコーディングの文字ではなく、UTF-16で使用するために予約されています。ここに私の推測です:プライベートな飛行機の文字を特殊なフォントと一緒に使って、アイコン(様々な矢、弾など)を提供するウェブデザインの現代の伝統があります。特にTwitterはこれを行います(Githubも同様です)。これは、HTMLページがイメージのロード時に保存する方法です(特殊フォントのベクトルアウトラインなので)。私はEmacsが送信する前にそれらを扱うと思います。 –

答えて

1

これはほぼ確実yasonのバグです。 JSONでは、BMP以外の文字がエスケープされている場合は、代理ペアを使用してエスケープされている必要があります。ここでU + 10000(必要に応じて「\ ud800 \ udc00」としてJSONにエスケープされ、バベルの変換は以下strinあるとして、私がバベルを使用)を用いて簡単な例は次のとおり

(map 'list #'char-code (yason:parse "\"\\ud800\\udc00\"")) 
    => (55296 56320) 

Unicodeコードポイント55296(小数)でありますサロゲートペアを開始し、UTF-16のサロゲートペア以外には表示しないでください。幸いにも、簡単に再びUTF-16に文字列をエンコードするためにバベルを使用することによって回避することができ:

(babel:octets-to-string (babel:string-to-octets (yason:parse "\"\\ud800\\udc00\"") :encoding :utf-16le) :encoding :utf-16le) 
    => "" 

をあなたは、この行を変更することにより、この問題を回避することができるはずです:へ

(yason:encode (funcall fn-convert (yason:parse data)) fout) 

UTF-16に変換して戻す中間文字列を使用します。我々は見つけるだろう -

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

関連する問題