2013-07-15 33 views
5

Tôi có một mã mà nếu được thực hiện từ dấu nhắc chất nhờn bên trong emacs chạy không có lỗi. Nếu tôi bắt đầu sbcl từ dấu nhắc, tôi đã nhận lỗi:lỗi mã hóa sbcl chỉ khi được thực hiện từ lời nhắc?

* (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] 

Các Mystery là trong cả hai trường hợp tôi đang sử dụng cùng sbcl 1.1.8 và cùng một máy, Mac OS 10.8.4. Bất kỳ ý tưởng?

Mã:

(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

tôi đề nghị bạn nên bắt đầu bằng cách giả định đây không phải là một vấn đề Yason - chúng tôi sẽ tìm hiểu nhanh chóng nếu có - và thêm mã sau vào mã của bạn: '(định dạng * standard-output *" ~ & ~ {~ x ~^~} "(bản đồ 'danh sách' dòng mã char))'. Dòng cuối cùng trong trường hợp lỗi có giống với dòng tương ứng trong môi trường SLIME không? –

+1

Có thể có các tệp có tên BRAvESP000.log trong nhiều hơn một thư mục và thư mục hiện tại khác nếu bạn đang ở chế độ SLIME hoặc nếu bạn đang khởi chạy SBCL theo cách thủ công. Hãy thử đường dẫn tuyệt đối. – acelent

+0

Nếu mã ký tự không phải là một sai lầm, nó thuộc về phạm vi Unicode của cặp thay thế. Đây không phải là các ký tự mã hóa UTF-8, chúng được dành riêng để sử dụng với UTF-16. Đây là dự đoán của tôi: có một truyền thống hiện đại trong thiết kế web để sử dụng các ký tự máy bay riêng cùng với một phông chữ đặc biệt để làm biểu tượng (chẳng hạn như các mũi tên khác nhau, dấu đầu dòng và vv). Twitter, đặc biệt, thực hiện điều đó (ví dụ như Github). Đây là một cách cho một trang HTML để lưu trên tải hình ảnh (vì đây là những phác thảo vector từ một phông chữ đặc biệt). Tôi sẽ tưởng tượng rằng Emacs giao dịch với họ trước khi gửi đi. –

Trả lời

1

Đây là gần như chắc chắn một lỗi trong Yason. JSON yêu cầu rằng nếu một ký tự không phải là BMP được thoát, nó được thực hiện thông qua một cặp thay thế. Dưới đây là một ví dụ đơn giản với U + 10000 (được tùy chọn thoát trong json như "\ ud800 \ udc00", tôi sử dụng babel như chuyển đổi babel là ít strin):

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

đang unicode điểm 55.296 (thập phân) là bắt đầu cho một cặp thay thế và không nên xuất hiện ngoại trừ cặp thay thế trong UTF-16. May mắn thay nó có thể dễ dàng làm việc xung quanh bằng cách sử dụng babel để mã hóa chuỗi sang UTF-16 và ngược lại:

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

Bạn nên có thể làm việc này bằng cách thay đổi dòng này:

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

Để sử dụng một chuỗi trung gian, mà bạn chuyển đổi thành UTF-16 và ngược lại.

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

Tôi đã gửi một bản vá đã được chấp nhận để sửa lỗi này trong Yason:

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

Các vấn đề liên quan