使用 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 崩溃

使用 RPostgreSQL 和 dplyr 将 R 连接到 Redshift 的理论是啥

如何使用 libssl 和 libpg 和 SSL 激活编译 RpostgreSQL