2016-07-07 67 views
6

Ho capito come scrivere stringhe Unicode, ma ancora perplesso dal motivo per cui funziona.Come scrivere una stringa Unicode in un file di testo in R Windows?

str <- "ỏ" 
Encoding(str) # UTF-8 
cat(str, file="no-iconv") # Written wrongly as <U+1ECF> 
cat(iconv(str, to="UTF-8"), file="yes-iconv") # Written correctly as ỏ 

capisco perché l'approccio no-iconv non funziona. È perché cat (e writeLines pure) convert the string into the native encoding first and then to the to= encoding. Su Windows, ciò significa che R converte in Windows-1252 per primo, che non può comprendere , risultante in <U+1ECF>.

Quello che non capisco è il motivo per cui l'approccio yes-iconv funziona. Se ho capito bene, cosa fa iconv qui è semplicemente per restituire una stringa con la codifica UTF-8. Ma str è già in UTF-8! Perché lo iconv dovrebbe fare qualche differenza? Inoltre, quando iconv(str, to="UTF-8") viene passato al cat, non dovrebbe cat rovinare tutto ancora una volta in primo luogo la conversione in Windows-1252?

+0

non so o utilizzare R me stesso, ma solo leggendo la documentazione, 'cat()' uscite stringhe di caratteri "così come sono", e il parametro '' mark' di iconv() 'è vero per impostazione predefinita, in modo chiamando 'iconv (str, to =" UTF-8 ")' segna esplicitamente il suo output come UTF-8 prima di passare a 'cat()'. Forse 'str <-" ỏ "' non sta marcando 'str' allo stesso modo? Puoi usare 'enc2utf8 (str)' o 'Encoding (str) <-" UTF-8 "' per convertire e marcare 'str' come UTF-8 senza usare' iconv() '. Questo probabilmente sta facendo la differenza con 'cat()'. –

risposta

2

Penso che impostare la codifica di (una copia di) str su "unknown" prima di utilizzare cat() sia meno magico e funzioni altrettanto bene. Penso che dovrebbe evitare qualsiasi conversione di set di caratteri indesiderati in cat().

Ecco un esempio esteso per dimostrare quello che penso succede nel esempio originale:

print_info <- function(x) { 
    print(x) 
    print(Encoding(x)) 
    str(x) 
    print(charToRaw(x)) 
} 

cat("(1) Original string (UTF-8)\n") 
str <- "\xe1\xbb\x8f" 
Encoding(str) <- "UTF-8" 
print_info(str) 
cat(str, file="no-iconv") 

cat("\n(2) Conversion to UTF-8, wrong input encoding (latin1)\n") 
## from = "" is conversion from current locale, forcing "latin1" here 
str2 <- iconv(str, from="latin1", to="UTF-8") 
print_info(str2) 
cat(str2, file="yes-iconv") 

cat("\n(3) Converting (2) explicitly to latin1\n") 
str3 <- iconv(str2, from="UTF-8", to="latin1") 
print_info(str3) 
cat(str3, file="latin") 

cat("\n(4) Setting encoding of (1) to \"unknown\"\n") 
str4 <- str 
Encoding(str4) <- "unknown" 
print_info(str4) 
cat(str4, file="unknown") 

In un locale "Latin-1" (vedi ?l10n_info) usati per R su Windows, i file di output "yes-iconv", "latin" e "unknown" dovrebbe essere corretto (sequenza di byte 0xe1, 0xbb, 0x8f che è "ỏ").

In una locale "UTF-8", i file "no-iconv" e "unknown" devono essere corretti.

L'uscita del codice di esempio è il seguente, utilizzando R 3.3.2 versione da 64 bit in esecuzione sul vino:

(1) Original string (UTF-8) 
[1] "ỏ" 
[1] "UTF-8" 
chr "<U+1ECF>""| __truncated__ 
[1] e1 bb 8f 

(2) Conversion to UTF-8, wrong input encoding (latin1) 
[1] "á»\u008f" 
[1] "UTF-8" 
chr "á»\u008f" 
[1] c3 a1 c2 bb c2 8f 

(3) Converting (2) explicitly to latin1 
[1] "á»" 
[1] "latin1" 
chr "á»" 
[1] e1 bb 8f 

(4) Setting encoding of (1) to "unknown" 
[1] "á»" 
[1] "unknown" 
chr "á»" 
[1] e1 bb 8f 

Nell'esempio originale, iconv() utilizza il from = "" argomento di default che mezzi di conversione da la locale corrente, che è effettivamente "latin1". Poiché la codifica di str è in realtà "UTF-8", la rappresentazione byte della stringa è distorta nello stadio (2), ma poi implicitamente ripristinato cat() quando (presumibilmente) converte la corda con l'ambiente corrente, come dimostrano la conversione equivalente nel passaggio (3).