使用 RPostgreSQL 进行 UTF-8 / Unicode 文本编码
Posted
技术标签:
【中文标题】使用 RPostgreSQL 进行 UTF-8 / Unicode 文本编码【英文标题】:UTF-8 / Unicode Text Encoding with RPostgreSQL 【发布时间】:2014-02-18 23:53:36 【问题描述】:我在直接链接到 PostgreSQL 数据库的 Windows 机器上运行 R。我没有使用 RODBC。我的数据库以 UTF-8 编码,由以下 R 命令确认:
dbGetQuery(con, "SHOW CLIENT_ENCODING")
# client_encoding
# 1 UTF8
但是,当某些文本被读入 R 时,它会在 R 中显示为奇怪的文本。
例如,以下文本显示在我的 PostgreSQL 数据库中: “史蒂芬”
导出到 R 后显示如下: “史蒂芬” (é 被编码为 é)
导入到 R 时,我使用dbConnect
命令建立连接,并使用dbGetQuery
命令使用 SQL 查询数据。在连接到数据库或运行查询时,我没有在任何地方指定任何文本编码。
我在网上搜索过,但找不到直接解决我的问题的方法。我找到了this link,但他们的问题在于我没有使用的 RODBC。
This link 有助于识别符号,但我不只是想在 R 中进行查找和替换...太多的数据。
我确实尝试运行以下命令,但收到了警告。
Sys.setlocale("LC_ALL", "en_US.UTF-8")
# [1] ""
# Warning message:
# In Sys.setlocale("LC_ALL", "en_US.UTF-8") :
# OS reports request to set locale to "en_US.UTF-8" cannot be honored
Sys.setenv(LANG="en_US.UTF-8")
Sys.setenv(LC_CTYPE="UTF-8")
警告出现在Sys.setlocale("LC_ALL", "en_US.UTF-8")
命令上。我的直觉是,这是 Windows 特有的问题,Mac/Linux/Unix 不会发生。
【问题讨论】:
请注意,client_encoding
不是您的数据库使用的实际编码。您可以使用psql -l
选项或\l
命令找到数据库的编码。
【参考方案1】:
导出到 R 后显示为:“Stéphane”(é 编码为 é)
您的 R 环境使用 1 字节非组合编码,例如 latin-1 或 windows-1252。在 Python 中见证这个测试,证明 é
的 utf-8 字节,就像它们是 latin-1 一样被解码,产生你看到的文本:
>>> print u"é".encode("utf-8").decode("latin-1")
é
SET client_encoding = 'windows-1252'
或修复您的 R 环境使用的编码。如果它在cmd.exe
控制台中运行,则需要使用chcp
控制台命令;否则它特定于你的 R 运行时。
【讨论】:
是的,这行得通。我在从 PostgreSQL 加载数据之前运行了命令postgresqlpqExec(con, "SET client_encoding = 'windows-1252'")
,即使系统返回FALSE
,它仍然会转换为所需的字符。谢谢!
@DavidL 请注意,如果您采用这种方法,并且您的数据包含无法在 windows-1252 中表示的字符,则查询将因编码错误而失败。如果可能的话,更好使用 Unicode 来获得你的 R 环境。
如何使用 Unicode 来设置你的 R 环境?【参考方案2】:
正如 Craig Ringer 所说,将 client_encoding
设置为 windows-1252 可能不是最好的选择。事实上,如果您检索的数据包含一个奇异字符,那么您就有麻烦了:
postgresqlExecStatement(conn, statement, ...) 中的错误:RS-DBI 驱动程序:(无法检索结果:错误:字符 0xcca7 的 编码“UTF8”在“WIN1252”中没有等价物)
另一方面,让你的 R 环境使用 Unicode 可能是不可能的(我和你有同样的问题,Sys.setlocale
...this question 也一样。)。
一种解决方法是使用如下函数手动声明所有数据的 UTF-8 编码:
set_utf8 <- function(x)
# Declare UTF-8 encoding on all character columns:
chr <- sapply(x, is.character)
x[, chr] <- lapply(x[, chr, drop = FALSE], `Encoding<-`, "UTF-8")
# Same on column names:
Encoding(names(x)) <- "UTF-8"
x
您必须在所有查询中使用此功能:
set_utf8(dbGetQuery(con, "SELECT myvar FROM mytable"))
编辑: 另一种可能性是使用 RPostgres 代替 RPostgreSQL。我对其进行了测试(使用与您的问题相同的配置),据我所知,所有声明的编码都自动设置为 UTF-8。
【讨论】:
我可以确认使用 RPostgres 可以解决问题。 Postgres 和 set_utf8 解决方案都运行良好。【参考方案3】:这将修复 Windows 中的任何 Unicode/UTF-8 问题。必须在查询数据库之前执行。
postgresqlpqExec(con, "SET client_encoding = 'windows-1252'")
取自提问者错误的自我回答,在问题修订历史中可见
【讨论】:
@Scarabee:我在发布之前进行了检查,Craig 对此的详细信息较少,只提到需要一些 R 运行时特定的方式来设置client_encoding
。【参考方案4】:
这样做:
con <- dbConnect("...", encoding = "latin1")
【讨论】:
我在 postgresqlNewConnection(drv, ...) 中遇到错误:未使用的参数 (encoding = "latin1")【参考方案5】:如果你使用 RPostgres::Postgres() 作为 dbConnect() 的第一个参数,通常你不会遇到编码问题。
我在遇到同样问题的地方尝试了这个脚本,现在我的重音字符没问题。
dbConnect(RPostgres::Postgres(),user="user",password="psw",host="host",port=5432,dbname="db_name")
【讨论】:
以上是关于使用 RPostgreSQL 进行 UTF-8 / Unicode 文本编码的主要内容,如果未能解决你的问题,请参考以下文章
R RPostgreSQL 使用 SSL 连接到远程 Postgres 数据库
如何使用 RPostgreSQL 将表写入 Panoply?
无法使用 RPostgreSQL 连接到 AWS Redshift
将 RpostgreSQL 与 sqldf 一起使用会使 R 崩溃