2016-07-07 10 views
6

私はUnicode文字列を書く方法を考えましたが、なぜそれが動作するのか困惑しました。R WindowsでテキストファイルにUnicode文字列を書き込む方法は?

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 ỏ 

私はno-iconvアプローチが機能しない理由を理解しています。これは、cat(およびwriteLinesでも同様)convert the string into the native encoding first and then to the to= encodingです。ウィンドウズでは、これは最初にをに変換することを意味し、を理解できず、<U+1ECF>になります。

私が理解できないのは、yes-iconvというアプローチが有効な理由です。私が正しく理解しているのであれば、iconvは単にUTF-8エンコーディングの文字列を返すだけです。しかしstrは既にUTF-8に入っています! iconvはなぜ違いがありますか?また、iconv(str, to="UTF-8")catに渡された場合、最初にWindows-1252に変換することによって、catすべてをもう一度混乱させるべきではありませんか?

+0

私は知らないのですが、マニュアルを読むだけで、 'cat()'は文字列をそのまま出力し、 'iconv()'の 'mark'パラメータはデフォルトでtrueです。 'iconv(str、to =" UTF-8 ")を呼び出すと、出力が' cat() 'に渡される前に明示的に出力がUTF-8としてマークされます。たぶん 'str < - "ỏ "'は同じ方法で 'str'をマーキングしていませんか? 'iconv()'を使わずに、 'enc2utf8(str)'や 'Encoding(str)< - " UTF-8 "'を明示的に変換してUTF-8としてマークすることができます。これはおそらく 'cat()'との違いになります。 –

答えて

2

私はcat()を使用する前に"unknown"str(のコピー)のエンコーディングを設定することが少ない魔法であると全く同じようにうまくいくと思います。私はcat()で不要な文字セットの変換を避けるべきだと思います。ここで

私は元の例で起こる考えるものを実証するために、拡張の例である:"Latin-1"ロケールで

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

?l10n_infoを参照)は、Windows上でRによって使用されるように、出力ファイル"yes-iconv""latin""unknown"必要があります(バイトシーケンス0xe1,0xbb,0x8f、これは"ỏ"です)。

"UTF-8"ロケールでは、"no-iconv""unknown"のファイルが正しいはずです。

ワインの上で実行されているR 3.3.2 64ビットWindowsバージョンを使用して、次のようにコード例の出力は、オリジナルの例で

(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 

iconv()から変換手段デフォルトfrom = ""引数を使用して、現在のロケールは、実質的に「latin1」です。 strのエンコーディングは実際には "UTF-8"なので、文字列のバイト表現はステップ(2)で歪められますが、cat()によって暗黙的に復元されます(実際には現在のロケールに変換されます)。ステップ(3)の等価変換。

関連する問題