我在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处理换行符的方式.
JD,我们在摘要包中通过serialize()
/来自raw
.这很好,因为您可以在SQL和其他地方存储序列化对象.我实际上将它存储为RData,这样更快load()
(没有解析!)和save()
.
或者,如果它必须是RawToChar()
和ascii然后使用这样的东西(直接从help(digest)
我们比较文件的序列化COPYING:
# 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>