2016-07-07 15 views
6

Tôi đã tìm cách viết các chuỗi Unicode, nhưng vẫn còn bối rối vì sao nó hoạt động.Cách viết chuỗi Unicode vào tệp văn bản trong 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 ỏ 

Tôi hiểu tại sao cách tiếp cận no-iconv không hoạt động. Đó là bởi vì cat (và writeLines cũng vậy) convert the string into the native encoding first and then to the to= encoding. Trên cửa sổ, điều này có nghĩa là R chuyển đổi thành Windows-1252 trước, không thể hiểu được , dẫn đến <U+1ECF>.

Điều tôi không hiểu là tại sao phương pháp tiếp cận yes-iconv hoạt động. Nếu tôi hiểu chính xác, những gì iconv làm ở đây chỉ đơn giản là để trả về một chuỗi với mã hóa UTF-8. Nhưng str đã có trong UTF-8! Tại sao nên iconv thực hiện bất kỳ sự khác biệt nào? Ngoài ra, khi iconv(str, to="UTF-8") được chuyển đến cat, không nên cat làm hỏng mọi thứ một lần nữa bằng cách chuyển đổi thành Windows-1252 trước tiên?

+0

Tôi không biết hoặc sử dụng R, nhưng chỉ đọc tài liệu, 'cat()' xuất ra chuỗi ký tự "như là", và tham số 'mark' của' biểu tượngv() 'là đúng theo mặc định, vì vậy gọi 'iconv (str, to =" UTF-8 ")' đánh dấu rõ ràng đầu ra của nó là UTF-8 trước khi nó được chuyển tới 'cat()'. Có lẽ 'str <-" ỏ "' không đánh dấu 'str' theo cùng một cách? Bạn có thể sử dụng 'enc2utf8 (str)' hoặc 'Encoding (str) <-" UTF-8 "' để chuyển đổi rõ ràng và đánh dấu 'str' là UTF-8 mà không sử dụng' iconv() '. Điều đó có thể tạo ra sự khác biệt với 'cat()'. –

Trả lời

2

Tôi nghĩ rằng việc đặt Mã hóa (bản sao) str thành "unknown" trước khi sử dụng cat() ít phép thuật hơn và cũng hoạt động tốt. Tôi nghĩ rằng nên tránh bất kỳ chuyển đổi tập hợp ký tự không mong muốn nào trong cat().

Dưới đây là một ví dụ mở rộng để chứng minh những gì tôi nghĩ rằng sẽ xảy ra trong ví dụ ban đầu:

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

Trong một miền địa phương "Latin-1" (xem ?l10n_info) như được sử dụng bởi R trên Windows, các file đầu ra "yes-iconv", "latin""unknown" nên đúng (chuỗi byte 0xe1, 0xbb, 0x8f"ỏ").

Trong miền địa phương "UTF-8", tệp "no-iconv""unknown" phải chính xác.

Đầu ra của mã ví dụ như sau, sử dụng R 3.3.2 64-bit phiên bản Windows đang chạy trên Wine:

(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 

Trong ví dụ ban đầu, iconv() sử dụng from = "" đối số mặc định có nghĩa là chuyển đổi từ miền địa phương hiện tại, có hiệu quả là "latin1". Bởi vì mã hóa của str thực sự là "UTF-8", biểu diễn byte của chuỗi bị bóp méo ở bước (2), nhưng sau đó được khôi phục hoàn toàn bằng cat() khi nó (có lẽ) chuyển chuỗi trở lại miền địa phương hiện tại, như được minh họa bằng chuyển đổi tương đương ở bước (3).

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