为什么在操作字符串时stringr会改变编码?

Art*_*hur 7 encoding r stringr data.table

有这种奇怪的行为stringr,这真让我烦恼.stringr在没有警告的情况下更改包含异国字符的某些字符串的编码,在我的情况下ø,å,æ,é和其他一些......如果你str_trim是一个字符矢量,那么具有异国情调字母的字符将被转换为新的编码.

letter1 <- readline('Gimme an ASCII character!')     # try q or a
letter2 <- readline('Gimme an non-ASCII character!') # try ø or é
Letters <- c(letter1, letter2)
Encoding(Letters)           # 'unknown'
Encoding(str_trim(Letters)) # mixed 'unknown' and 'UTF-8'
Run Code Online (Sandbox Code Playgroud)

这是一个问题,因为我使用data.table来快速合并大表,而data.table不支持混合编码,因为我找不到回归统一编码的方法.

任何解决方法?

编辑:我以为我可以回到基本功能,但他们不保护编码.paste保留它,但不是sub例如.

 Encoding(paste(' ', Letters))                 # 'unknown'
 Encoding(str_c(' ', Letters))                 # mixed
 Encoding(sub('^ +', '', paste(' ', Letters))) # mixed
Run Code Online (Sandbox Code Playgroud)

Kon*_*lph 1

R 并不总是能够轻松地在编码之间进行转换(有iconv相应的函数,但该函数接受的内容取决于平台)。但是,至少您始终可以将字符串的编码标记重置为 \xe2\x80\x9cunknown\xe2\x80\x9d:

\n\n
Letters = str_trim(Letters)\nEncoding(Letters)\n# [1] "unknown" "UTF-8"\nEncoding(Letters) = \'\'\nEncoding(Letters)\n# [1] "unknown" "unknown"\n
Run Code Online (Sandbox Code Playgroud)\n\n

但是,请注意,这仅标记字符串的编码,它实际上并没有重新编码字符串。因此,这可能会导致数据出现乱码。正如评论中提到的,这充其量只是一种黑客攻击,而不是问题的实际解决方案。

\n\n

Encoding举例说明了 R\xe2\x80\x99s 无法正常使用编码的问题。文档说:

\n\n
\n

ASCII 字符串永远不会用声明的编码进行标记,因为它们的表示在所有支持的编码中都是相同的。

\n
\n\n

\xe2\x80\xa6\xc2\xa0 这显然根本没有帮助(而且也有点误导;仅由 < 128 的代码点组成的 UTF-8 字符串可能看起来与 ASCII 字符串无法区分,但对其进行操作应该会产生不同的结果取决于编码,这就是为什么应该有效地标记它)。

\n\n

有趣的是,这里 \xe2\x80\x94 都不会enc2nativeenc2utf8所需的事情,两者都会为 中的两个字符串产生不同的编码,这是上面引用的问题Letters的直接结果。Encoding

\n

  • 这个答案中建议的方法并不是一个好的方法。一方面,这在 Windows(或者可能是默认编码不是 UTF8 的任何平台)上根本不起作用。另一方面,它没有清楚地区分_改变_编码(例如,使用“iconv”)和_标记_编码(使用“Encoding”)。更一般地说,它试图解决的问题实际上并不存在;`str_trim` 和 stringr 包中的其他函数返回的字符串完全正常,并且元素_没有不同的编码_。如文档所述,“Encoding”不标记 ascii 字符。 (2认同)