我在R中有一个进程,它创建了一堆对象,将它们序列化,并将它们放入纯文本文件中。这似乎是处理事情的一种非常好的方法,因为我正在使用Hadoop并且所有输出都需要通过stdin和stdout进行流式处理。
我留下的问题是如何从文本文件中读取这些对象并返回到桌面计算机上的R中。这是一个说明挑战的工作示例:
让我们创建一个tmp文件并将一个对象写入其中。这个对象只是一个向量:
outCon <- file("c:/tmp", "w")
mychars <- rawToChar(serialize(1:10, NULL, ascii=T))
cat(mychars, file=outCon)
close(outCon)
mychars对象如下所示:
> mychars
[1] "A\n2\n133633\n131840\n13\n10\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n"
当写入文本文件时,它看起来像这样:
A
2
133633
131840
13
10
1
2
3
4
5
6
7
8
9
10
我可能忽略了一些非常明显的东西,但是如何将此文件读回R并反序列化该对象?当我尝试scan()或readLines()时,他们都希望将新行字符视为记录分隔符,最后我得到一个向量,其中每个元素都是文本文件中的一行。我真正想要的是一个包含文件全部内容的文本字符串。然后我可以反序列化字符串。
Perl会将换行符读回字符串,但我无法弄清楚如何覆盖R处理换行符的方式。
答案 0 :(得分:8)
JD,我们在digest包中通过serialize()
到/ raw
进行此操作。这很好,因为您可以在SQL和其他地方存储序列化对象。我实际上将它存储为RData,这对load()
(没有解析!)和save()
更快。
或者,如果它必须是RawToChar()
和ascii,那么使用类似的东西(直接从help(digest)
直接获取文件的序列化来复制:
# test 'length' parameter and file input
fname <- file.path(R.home(),"COPYING")
x <- readChar(fname, file.info(fname)$size) # read file
for (alg in c("sha1", "md5", "crc32")) {
# partial file
h1 <- digest(x , length=18000, algo=alg, serialize=FALSE)
h2 <- digest(fname, length=18000, algo=alg, serialize=FALSE, file=TRUE)
h3 <- digest( substr(x,1,18000) , algo=alg, serialize=FALSE)
stopifnot( identical(h1,h2), identical(h1,h3) )
# whole file
h1 <- digest(x , algo=alg, serialize=FALSE)
h2 <- digest(fname, algo=alg, serialize=FALSE, file=TRUE)
stopifnot( identical(h1,h2) )
}
所以你的例子就是这样:
R> outCon <- file("/tmp/jd.txt", "w")
R> mychars <- rawToChar(serialize(1:10, NULL, ascii=T))
R> cat(mychars, file=outCon); close(outCon)
R> fname <- "/tmp/jd.txt"
R> readChar(fname, file.info(fname)$size)
[1] "A\n2\n133633\n131840\n13\n10\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n"
R> unserialize(charToRaw(readChar(fname, file.info(fname)$size)))
[1] 1 2 3 4 5 6 7 8 9 10
R>