通过 ODBC 从 MS SQL 读取后编码出现 R 问题

R problems with encoding after reading from MS SQL via ODBC

我们在不同的虚拟机上有一个数据库和 R 脚本 运行。 首先我们连接到 db

con <- dbConnect(
  odbc(),
  Driver = "SQL Server",
  Server = "server", Database = "db", UID = "uid", PWD = "pwd",
  encoding = "UTF-8"
)

并收集数据

data <- dbGetQuery(con, "SELECT * FROM TableName")

问题如下:当不同的机器运行相同的脚本时,对于其中一些我们面临字符变量编码问题。

例如,这是我们在机器 A 上的内容

> data$char_var[1]
[1] "фамилия"
> Encoding(data$char_var[1])
[1] "UTF-8"
> Sys.getlocale()
[1] "LC_COLLATE=Russian_Russia.1251;LC_CTYPE=Russian_Russia.1251;LC_MONETARY=Russian_Russia.1251;LC_NUMERIC=C;LC_TIME=Russian_Russia.1251"
> Encoding(data$char_var[1]) <- "1251"
> data$char_var[1]
[1] "гревцев"

这就是我们在机器 B 上的内容

> data$char_var[1]
[1] "<e3><f0><e5><e2><f6><e5><e2>"
> Encoding(data$char_var[1])
[1] "UTF-8"
> Sys.getlocale()
[1] "LC_COLLATE=Russian_Russia.1251;LC_CTYPE=Russian_Russia.1251;LC_MONETARY=Russian_Russia.1251;LC_NUMERIC=C;LC_TIME=Russian_Russia.1251"
> Encoding(data$char_var[1]) <- "1251"
> data$char_var[1]
[1] "фамилия"

第一个脚本 returns 乱码,但它正确地打印了初始值。机器 B 上的相同代码 运行 最初打印 utf-8,然后打印 returns 编码值。造成这种差异的原因可能是什么?

因此,我们需要一个具有相同“фамилия”输出值的脚本,以在仪表板上显示它。

根据您调用 Encoding(data$char_var[1]) 的结果,两台机器都声明 returned 结果使用 UTF-8 编码。

在第一台机器上,这似乎是正确的,因为您看到的是有效输出。然后你通过将编码错误地声明为 "1251" 来搞砸它,你会看到乱码。

在第二台机器上,您收到的结果声明为 UTF-8,但实际上不是(这就是为什么一开始看起来像乱码)。当您将声明的编码更改为 "1251" 时,它看起来没问题,所以它一直都是这样。

所以你有两个选择:

  • 确保两台机器关于 return 来自 dbGetQuery 的内容是一致的。您可以处理任何一种编码,但您需要知道它是什么并确保它被正确声明。

  • 或者,尝试检测正在 returned 的内容,并适当地声明它。执行此操作的一种方法可能是将已知字符串放入数据库并将结果与​​该字符串进行比较。如果你知道你应该得到 "фамилия" 而你得到了其他东西,请切换声明的编码。您也可以尝试 readr::guess_encoding() 函数。

另一个问题是某些下游函数可能只能处理 UTF-8 和 1251 编码中的一种。 (Windows R 在非本地编码方面真的很糟糕,而 UTF-8 在 Windows 上从来不是本地编码。)在那种情况下,您可能想要实际转换为通用编码。您可以使用 iconv() 函数来执行此操作,例如

iconv(char_var, from = "cp1251", to = "UTF-8")

将尝试转换为 UTF-8。