- 已编辑
问题描述
最近的数据分析涉及英语和日语文档,时不时出现乱码,正在尝试一个个解决。其中一个是用list.files()
读取文件名后,在RStudio的Console板块输出结果为乱码的问题。查阅字符编码相关资料,加上自己尝试更改电脑语言和区域设置后,认为这主要和电脑系统的区域设置有关,详细位置是Settings > Region > Additional date, time & regional > Change date, time, or number format > Administrative > Language for non-Unicode programs settings,下面简称该项设置为“非Unicode程序语言设置”。实验过程和代码详述如下。我的问题是:
- 能否在不改变电脑非Unicode程序语言设置的情况下正确读取并显示示例日文文件名?
- 通过改变电脑非Unicode程序语言设置和
Sys.setlocale()
实现正确读取的方法会不会有什么副作用?比如在后续读取其他语言的数据、数据文件或文件名的时候是否会出问题?
代码和结果
首先在目录C:\Users\kangj\Documents\R\Other\cosx_mojibake\File
下放入一个PDF文件,命令为“京都市とさいたま市.pdf”。然后在不同系统语言、区域格式设置和非Unicode程序语言设置下读取该文件的文件名,看看是否正常显示,以及能否正常查找到这个文件。这三个因素中,系统语言就是电脑的界面语言,区域格式设置则和日期时间等的显示格式有关,非Unicode程序语言设置的话,我不太清楚,似乎和一些非UTF-8软件或文件的默认打开方式有关?由于经过简单对比发现,系统语言和区域格式设置这两个因素和本问题没有关系,所以这里只展示在不同非Unicode程序语言设置下的结果,以下代码系统语言均为英语,区域格式设置也均为英语。此外,在非Unicode程序语言设置中,有一个“Use Unicode UTF-8 for worldwide language support”的选框,均不勾选。以下代码中,前面带一个#
的是代码注释,带##
的是运行结果。
第1种情况 非Unicode程序语言设置为日语:
# 注意先设置好工作路径为“京都市とさいたま市.pdf”所在文件夹
# 第一步:不改变Sys.setlocale()测试
# 查看此时的sessionInfo()
sessionInfo()
##R version 4.0.3 (2020-10-10)
##Platform: x86_64-w64-mingw32/x64 (64-bit)
##Running under: Windows 10 x64 (build 19042)
##
##Matrix products: default
##
##locale:
##[1] LC_COLLATE=Japanese_Japan.932 LC_CTYPE=Japanese_Japan.932
##[3] LC_MONETARY=Japanese_Japan.932 LC_NUMERIC=C
##[5] LC_TIME=Japanese_Japan.932
##
##attached base packages:
##[1] stats graphics grDevices utils datasets methods base
##
##loaded via a namespace (and not attached):
## [1] compiler_4.0.3 htmltools_0.5.0 tools_4.0.3 yaml_2.2.1 rmarkdown_2.5
## [6] knitr_1.30 xfun_0.18 digest_0.6.27 rlang_0.4.8 evaluate_0.14
list.files()
##[1] "京都市とさいたま市.pdf"
# 将结果代入看看能否查找到对应文件
"‹ž“sŽs‚Æ‚³‚¢‚½‚ÜŽs.pdf" %in% list.files()
##[1] FALSE
# 将原文件名代入看能否查找到
"京都市とさいたま市.pdf" %in% list.files()
##[1] TRUE
# 第二步:改变Sys.setlocale()后测试
Sys.setlocale(category = "LC_ALL", locale = "Japanese")
##[1] "LC_COLLATE=Japanese_Japan.932;LC_CTYPE=Japanese_Japan.932;
##LC_MONETARY=Japanese_Japan.932;LC_NUMERIC=C;LC_TIME=Japanese_Japan.932"
sessionInfo()
##R version 4.0.3 (2020-10-10)
##Platform: x86_64-w64-mingw32/x64 (64-bit)
##Running under: Windows 10 x64 (build 19042)
##
##Matrix products: default
##
##locale:
##[1] LC_COLLATE=Japanese_Japan.932 LC_CTYPE=Japanese_Japan.932
##[3] LC_MONETARY=Japanese_Japan.932 LC_NUMERIC=C
##[5] LC_TIME=Japanese_Japan.932
##
##attached base packages:
##[1] stats graphics grDevices utils datasets methods base
##
##loaded via a namespace (and not attached):
## [1] compiler_4.0.3 htmltools_0.5.0 tools_4.0.3 yaml_2.2.1 rmarkdown_2.5
## [6] knitr_1.30 xfun_0.18 digest_0.6.27 rlang_0.4.8 evaluate_0.14
list.files()
##[1] "京都市とさいたま市.pdf"
"京都市とさいたま市.pdf" %in% list.files()
##[1] TRUE
# 那通过第一步生成的乱码还能查找到对应文件吗
"‹ž“sŽs‚Æ‚³‚¢‚½‚ÜŽs.pdf" %in% list.files()
##[1] FALSE
# 这时候如果把Sys.setlocale()又改回英语的话,结果会和第一步相同,不赘述
第2种情况 非Unicode程序语言设置为中文:
# 第一步:不改变Sys.setlocale()测试
# 查看此时的sessionInfo()
sessionInfo()
##R version 4.0.3 (2020-10-10)
##Platform: x86_64-w64-mingw32/x64 (64-bit)
##Running under: Windows 10 x64 (build 19042)
##
##Matrix products: default
##
##locale:
##[1] LC_COLLATE=Japanese_Japan.932 LC_CTYPE=Japanese_Japan.932
##[3] LC_MONETARY=Japanese_Japan.932 LC_NUMERIC=C
##[5] LC_TIME=Japanese_Japan.932
##system code page: 1252
##
##attached base packages:
##[1] stats graphics grDevices utils datasets methods base
##
##loaded via a namespace (and not attached):
## [1] compiler_4.0.3 htmltools_0.5.0 tools_4.0.3 yaml_2.2.1 rmarkdown_2.5
## [6] knitr_1.30 xfun_0.18 digest_0.6.27 rlang_0.4.8 evaluate_0.14
list.files()
##[1] "?????????.pdf"
# 将结果代入看看能否查找到对应文件
"?????????.pdf" %in% list.files()
##[1] TRUE
# 将原文件名代入看能否查找到
"京都市とさいたま市.pdf" %in% list.files()
##[1] FALSE
# 第二步:改变Sys.setlocale()后测试
Sys.setlocale(category = "LC_ALL", locale = "Japanese")
##[1] "LC_COLLATE=Japanese_Japan.932;LC_CTYPE=Japanese_Japan.932;
##LC_MONETARY=Japanese_Japan.932;LC_NUMERIC=C;LC_TIME=Japanese_Japan.932"
sessionInfo()
##R version 4.0.3 (2020-10-10)
##Platform: x86_64-w64-mingw32/x64 (64-bit)
##Running under: Windows 10 x64 (build 19042)
##
##Matrix products: default
##
##locale:
##[1] LC_COLLATE=Japanese_Japan.932 LC_CTYPE=Japanese_Japan.932
##[3] LC_MONETARY=Japanese_Japan.932 LC_NUMERIC=C
##[5] LC_TIME=Japanese_Japan.932
##system code page: 1252
##
##attached base packages:
##[1] stats graphics grDevices utils datasets methods base
##
##loaded via a namespace (and not attached):
## [1] compiler_4.0.3 htmltools_0.5.0 tools_4.0.3 yaml_2.2.1 rmarkdown_2.5
## [6] knitr_1.30 xfun_0.18 digest_0.6.27 rlang_0.4.8 evaluate_0.14
list.files()
##[1] "?????????.pdf"
# 将原文件名代入看能否查找到
"京都市とさいたま市.pdf" %in% list.files()
##[1] FALSE
# 通过和第一步生成的乱码一致的这个文件名查找,还能找到对应文件吗
"?????????.pdf" %in% list.files()
##[1] TRUE
可见只有在满足两个条件,即非Unicode程序语言设置为日语,并且在RStudio中设置Sys.setlocale(category = "LC_ALL", locale = "Japanese")
的情况下,才能在Console面板上正确显示示例日语文件名。对于字符编码所知甚少的我而言,这就像是一个电路黑箱,而这两个条件就像是通向小灯泡的串联电路一样……所以有了本文开头提到的两个问题,在此重申并补充一下问题:
- 通过改变电脑非Unicode程序语言设置和
Sys.setlocale()
实现正确读取的原因是什么?我的猜测是:RStudio中代码在访问目标文件夹中的日语文件名文件时,采用的时系统的非Unicode程序语言设置,只有该设置为日语时,读入的“某个值”才是日语,然后这个值要输出到RStudio的Console面板时会再经历一次转码,这个过程中如果RStudio的Sys.setlocale()
不是日语的话,就会输出乱码。不知道这个猜测距离真相有多远。 - 能否在不改变电脑非Unicode程序语言设置的情况下正确读取并显示示例日文文件名?比如通过某些指令中的
encoding
或者fileEncoding
选项,或者是通过iconv()
函数转码?有这个问题,原因主要是怕系统设置的更改会影响其他软件,比如现在我打开*.csv
或者MS Excel文件的时候,字体就怪怪的,可能被当作日语处理了吧。 - 通过改变电脑非Unicode程序语言设置和
Sys.setlocale()
实现正确读取的方法会不会有什么副作用?比如在后续读取其他语言的数据、数据文件或文件名的时候是否会出问题?