为啥 R 将 UTF-8 标头作为文本读取?

Posted

技术标签:

【中文标题】为啥 R 将 UTF-8 标头作为文本读取?【英文标题】:Why is R reading UTF-8 header as text?为什么 R 将 UTF-8 标头作为文本读取? 【发布时间】:2013-11-25 01:06:13 【问题描述】:

我将 Excel 表格保存为文本 (*.txt)。不幸的是,Excel 不允许我选择编码。所以我需要在记事本中打开它(以 ANSI 格式打开)并将其保存为 UTF-8。然后,当我在 R 中阅读它时:

data <- read.csv("my_file.txt",header=TRUE,sep="\t",encoding="UTF-8")

它显示以“X.U.FEFF.”开头的第一列的名称。我知道这些是为告诉任何程序文件是 UTF-8 格式而保留的字节。所以它不应该显示为文本!这是一个错误吗?还是我错过了一些选择?提前致谢!

【问题讨论】:

尝试使用read.csv 参数check.names=FALSE。请注意,如果您使用它,您将无法使用 $ 表示法直接引用列。 UTF-8 文件应该包含字节顺序标记,请参阅RFC 3629 以获得解释。 谢谢@Matthew。它部分工作。 X.U.FEFF 不见了,但我不能再按名称引用第一列(尽管其他列仍然有效)。我仍然认为这是 R 未来版本中需要解决的错误。 如果你把它们放在引号里,你可以通过名字来引用它们,例如,yourdf$"first col" @Zack,我见过一些带有这些第一个字节的 UTF-8 文件,所以我认为这是一个规则。不是什么大问题,因为我总是可以重命名第一列,只是认为它应该有一天会解决。 【参考方案1】:

read.csv 中的大多数参数都是虚拟参数——包括fileEncoding

改用read.table

 read.table("my_file.txt", header=TRUE, sep="\t", fileEncoding="UTF-8")

【讨论】:

使用 read.table 我收到一个错误:“扫描错误(文件,内容,nmax,sep,dec,quote,skip,nlines,na.strings,:第 9191 行没有 25 个元素"。我的阅读评论其实比较复杂,就是:data 太棒了!然后它起作用了。现在你只需要清理你的源文件;)在纯文本编辑器中打开它(我喜欢 sublime text 3),到第 9191 行并检查它 谢谢,@Ricardo。我只需要comment.char=""。但现在它的行为与 read.csv 完全相同... :(【参考方案2】:

来自 cmets 的可能解决方案:

尝试使用 read.csv 参数 check.names=FALSE。请注意,如果您使用它,您将无法使用 $ 表示法直接引用列,除非您将名称括在引号中。例如:yourdf$"first col"

【讨论】:

【参考方案3】:

所以我打算向您说明如何手动打开文件并检查和丢弃 BOM,但后来我注意到了这一点(?file):

从 R 3.0.0 开始,编码“UTF-8-BOM”被接受,并将 如果存在,则删除字节顺序标记(通常用于文件 和由 Microsoft 应用程序生成的网页)。

这意味着如果你有一个足够新的 R 解释器,

read.csv("my_file.txt", fileEncoding="UTF-8-BOM", ...other args...)

应该做你想做的。

【讨论】:

嗯嗯差不多了。现在是“X.U.FEFF”。变成了“我..” 看起来该文件实际上不是 UTF-8。有什么方法可以向我们展示文件第一行的十六进制转储? (在大多数 Unix 系统上,head -1 my_file.txt | hexdump -C 会给你一个很好的十六进制转储,但我不知道 Windows 等价物。) 在 DOS 提示符下,调试会执行此操作。前三个字节是 EF BB BF。 (我将文件保存在记事本 5.1 build 2600、Windows XP SP3 中,它说格式是 UTF-8)。该行的其余部分是列名的 ASCII。 EF BB BF 43 4F 4C 45 43 41 4F 09 是的,我有 R 3.0.1。我下载了 Notepad++,它让我可以选择在有和没有 BOM 的情况下进行保存。似乎 R 无法处理 BOM。【参考方案4】:

我在使用read.csv(使用encoding="UTF-87-BOM")、read.tableread_csvreadr 包加载csv 文件时遇到了同样的问题。这些尝试都没有成功。

我绝对不能使用 BOM 标记,因为在子设置我的数据时(使用两种方法 subset()df[df$var=="value",]),第一行没有被考虑在内。

我终于找到了使 BOM 标记消失的解决方法。使用 read.csv 函数,我刚刚在参数 col.names = ... 中为我的列名定义了一个字符串向量。这就像一个魅力,我可以毫无问题地对我的数据进行子集化。

我使用 R 版本 3.5.0

【讨论】:

以上是关于为啥 R 将 UTF-8 标头作为文本读取?的主要内容,如果未能解决你的问题,请参考以下文章

在R中读取具有多个空格作为分隔符的文本文件

无法以纯文本格式读取文件

文件读取

为啥C语言输出文件内容乱码

python中文件操作

Windows上的R:字符编码地狱