使用fread导入CSV时出现“字符串中嵌入了空字节”错误。

40

我有一个很大的文件(3.5G),我正在尝试使用data.table::fread导入。

它最初是从rpt文件中打开为文本,然后保存为CSV格式创建的。

对于较小的文件(具有相同类型的数据-相同的列等),这个方法运行得很好。但这个文件的时间跨度更长、范围更广。

当我尝试运行

mydata <- fread("mycsv.csv")

我遇到了错误:

Error in fread("mycsv.csv") : embedded nul in string: 'y\0e\0a\0r\0'

这是什么意思?


3
看起来是UTF-16编码(每个字符通常使用2个或更多字节,几乎总是2个字节)。对于ASCII码,你会看到ASCII值,然后跟着一个0字节。 - Matt Chambers
2
当我加载从大型数据集生成的RData文件时,我遇到了同样的问题。我重新生成了RData,问题就消失了。看起来是由于我的RAM达到最大值时引起的。 - Cyrille
当您试图使用fread不当地打开RDS文件时,也会出现此错误。不要问我怎么知道的。 - Brandon Bertelsen
7个回答

22

我们可以使用类似以下的方法来删除命令行中的空终止符:

sed 's/\\0//g' mycsv.csv > mycsv.csv

就像@marbel建议的那样,fread允许你在文本中传递sed调用,例如:

fread("sed 's/\\0//g' mycsv.csv")

2
谢谢回复。我不太确定如何在R中输入它。我意识到一件事,显然,错误告诉我嵌入的nul在字符串“year”中,这是csv的第一行的第一个单词(它是第一列标题)。完整的错误是[Error in fread("allpcts90days1.csv"): embedded nul in string: 'y\0e\0a\0r\0']你知道这是什么意思吗?当我在文本编辑器(TextPad或UltraEdit,因为它们可以处理这么大的文件)中查看文本时,我没有看到任何异常。 - datahappy
1
你的文本文件中包含了ASCII保留用于终止字符串的字符。你需要在Linux命令行下运行它,或者如果你使用的是Windows系统,可以搜索“如何从Windows文件中删除特殊字符”。 - Robert Krzyzanowski
26
fread 函数允许你在文本中传递 sed 调用,例如:fread("sed 's/\\0//g' mycsv.csv") - marbel
它说:'sed'不被识别为内部或外部命令,此外我还遇到了“空文件错误”。 - mRiddle
我认为sep可能是@RobertKrzyzanowski所提到的参数? - Ben
sed是Unix实用程序,如果您没有安装/激活WSL,则无法在Windows上使用它。如果您不知道sed是什么,那么您可能还没有激活WSL。我也不知道如何在Windows上做这些事情;但应该有一种方法。罗伯特建议谷歌一下。否则,在相关文件夹中安装WSL并在Linux终端中运行该命令不应太麻烦。尝试在fread调用内部使用它将更加困难。 - Fons MA

13

在这种情况下,您可以使用read.csv并将fileEncoding设置为UTF-16LE,而不是使用fread

read.csv("mycsv.csv",fileEncoding="UTF-16LE")

考虑到你的数据规模,使用read.csv可能需要几分钟时间,但我认为这并不是什么大问题。


1
有了这么多的数据,实际上可能需要接近一个小时的时间。 - Love-R
根据我的经验,加载3.5GB的数据很难超过15分钟,除非在一些非常极端的情况下。 - Fan Wang
@FanWang 这取决于列的类型。 - jangorecki

5
你可以测试这个小函数:
cleanFiles<-function(file,newfile){
  writeLines(iconv(readLines(file,skipNul = TRUE)),newfile)
}

这对我有用


4
一种非技术的解决方法是:
  1. 打开出问题的 .csv 文件

  2. Ctrl+A (全选)

  3. 新建一个 Excel 工作表

  4. 右键点击并选择“以数值形式粘贴”

  5. 保存并使用这个文件替换原始文件。

对我来说有效,并且不会花费太多时间。

2
如果您在ASCII文件中看到了NUL (x00)字符,可以这样做:data.table::fread(text = readLines(pathIn, skipNul = T), ...)。"..."代表其他参数。最初的回答。

1

我遇到了类似的错误,分享一下以防其他人遇到同样的问题 -

  embedded nul in string: '\0HA\xa8S\001\0\0\0\xd8@\xa8S\001\0\0\0h@\xa8S\001\0\0\0\xf8?\xa8S\001\0\0\0\x88'
Calls: as.data.table -> fread

这个问题的原因是不同的列长度,我的第一列(标题)比其余列要短。

0
我发现相同的错误可能是由于扩展名与压缩方式不匹配的压缩的csv文件引起的。
例如,对于使用fwrite(mydata, "myfile.csv", compress = "gzip")写入的文件。这里的选项compress = "gzip"创建了一个压缩文件,它不是一个csv文件应该是的文本文件。
在这种情况下,文件被压缩了,但文件扩展名没有显示出来,fread在读取之前无法自动解压缩文件。
你可以在UNIX终端中执行head myfile.csv来查看文件是否被压缩,如果输出的结果是类似于��pG*ʵ��9的内容,而不是你所期望的内容。
在我的情况下,只需将文件扩展名改为.csv.gz,然后使用fread读取即可。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接