2013-07-15 15 views
5

Ho un codice che se eseguito dal prompt slime all'interno di emacs viene eseguito senza errori. Se ho iniziato SBCL dal richiamo, ho ottenuto l'errore:errore di codifica sbcl solo quando eseguito dal prompt?

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

Il mistero è che in entrambi i casi io sto usando lo stesso SBCL 1.1.8 e la stessa macchina, Mac OS 10.8.4. Qualche idea?

Il codice:

(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

io suggerisco di iniziare assumendo questo non è un problema Yason - lo scopriremo rapidamente se lo è - e aggiungi quanto segue al tuo codice: '(formato * standard-output *" ~ & ~ {~ x ~^~} "(linea 'char' code 'lista'))'. La riga finale nel caso in cui si è verificato un errore è la stessa della riga corrispondente nell'ambiente SLIME? –

+1

Forse ci sono file chiamati BRAvESP000.log in più di una directory, e la directory corrente è diversa se sei in SLIME o se stai lanciando manualmente SBCL. Prova percorsi assoluti. – acelent

+0

Se il codice carattere non è un errore, appartiene all'intervallo Unicode di coppie surrogate. Questi non sono caratteri della codifica UTF-8, sono riservati per l'uso con UTF-16. Ecco la mia ipotesi: c'è una tradizione moderna nel web design di usare personaggi di aerei privati ​​insieme a un font speciale da usare come icone (come varie frecce, pallottole e così via). Twitter, in particolare, lo fa (così anche Github per esempio). Questo è un modo per salvare una pagina HTML sul caricamento delle immagini (dato che si tratta di profili vettoriali di un font speciale). Immagino che Emacs si occupi di loro prima di inviare. –

risposta

1

Questo è quasi certamente un bug in Yason. JSON richiede che, se un personaggio non BMP è sfuggito, lo fa attraverso una coppia surrogata. Ecco un semplice esempio con U + 10000 (che è eventualmente sfuggito in json come "\ ud800 \ udc00"; Uso babel la conversione di babel è meno ela):

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

codice unicode punto 55296 (decimale) è il iniziare per una coppia surrogata e non dovrebbe apparire se non come una coppia surrogata in UTF-16. Fortunatamente può essere facilmente aggirata utilizzando babel per codificare la stringa in UTF-16 e viceversa:

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

Si dovrebbe essere in grado di ovviare a questo modificando questa linea:

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

Per usa una stringa intermedia, che converti in UTF-16 e viceversa.

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

ho presentato una patch che è stato accettato per risolvere questo problema in Yason:

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

Problemi correlati