R:从序列化对象中创建CSV

时间:2010-06-24 21:34:25

标签: r hadoop serialization

我正在尝试获取列表并序列化每个项目并将其放入CSV文件中,并使用键创建具有键/值对的文本文件。最终这将通过Hadoop流式传输,所以在你问之前,我认为它确实需要在文本文件中。 (但我对其他想法持开放态度)这一切看起来似乎很简单。但我不能完全按照我想要的方式进行序列化(still)。

如果我这样做:

> rawToChar(serialize("blah", NULL, ascii=T))
[1] "A\n2\n133888\n131840\n16\n1\n9\n4\nblah\n"

然后我有那些麻烦\ n后来搞砸了我的CSV解析。我可以进入并用其他字符串替换\ n,我并不反对这样做。然而,这看起来有点混乱。

想到的另一个选项是省略rawToChar()调用并将原始ascii抽入文本文件中:

> serialize("blah", NULL, ascii=T)
 [1] 41 0a 32 0a 31 33 33 38 38 38 0a 31 33 31 38 34 30 0a 31 36 0a 31 0a 39 0a
[26] 34 0a 62 6c 61 68 0a

好吧,如果我只是将其转储到文本文件中,我会在列表中的每个元素之后得到\ n。所以我尝试了一点粘贴/崩溃:

> ser <- serialize("blah", NULL, ascii=T)
> ser2 <- paste(ser, collapse="")
> ser2
[1] "410a320a3133333838380a3133313834300a31360a310a390a340a626c61680a"

现在这是我可以写入CSV文本文件的值!只有......我如何在以后再将其变回原始状态?让我们只取第一个十六进制元素:41我甚至无法弄清楚如何创建一个原始项列表并将十六进制值41推入其中一个元素。当我尝试将原始十六进制值推入原始列表时,我最终会得到这样的结果:

> r <- raw(1)
> r[1] <- 41
Error in r[1] <- 41 : 
  incompatible types (from double to raw) in subassignment type fix
> r[1] <- as.raw(41)
> r[1]
[1] 29 

扯淡! 29!= 41(当然,除了非常大的29值和41的非常小的值)

关于如何破解这个坚果的任何想法?

3 个答案:

答案 0 :(得分:3)

caTools有一个Base64编码器解码器,您可以使用:

> library(caTools)
> s<-base64encode(serialize("blah",NULL))
> s
[1] "WAoAAAACAAIKAQACAwAAAAAQAAAAAQAAAAkAAAAEYmxhaA=="
> unserialize(base64decode(s,"raw"))
[1] "blah"

答案 1 :(得分:1)

感谢jmoy的出色回答。我用他的推荐,效果很好。对于最终来到这里的未来搭便车者,我将离开我的功能,将列表转换为序列化的CSV文本文件,然后将其转回列表。我将这篇文章标记为社区维基。如果有更简洁的方法可以编辑它,请随意编辑它:

listToCsv <- function(inList, outFileName){
  require(caTools)
  if (is.list(inList) == F) 
        stop("listToCsv: The input list fails the is.list() check.")
  fileName <- outFileName
  cat("", file=fileName, append=F)

  i <- 1
  for (item in inList) {
    myLine <- paste(i, ",", base64encode(serialize(item, NULL, ascii=T)), "\n", sep="")
    cat(myLine, file=fileName, append=T) 
    i <- i+1
  }
}

csvToList <- function(inFileName){
  require(caTools)
  linesIn <- readLines(fileName, n=-1)
  outList <- NULL

  i <- 1
  for (line in linesIn){
    outList[[i]] <- unserialize(base64decode(strsplit(linesIn[[i]], split=",")[[1]][[2]], "raw"))
    i <- i+1
  }
  return(outList)
}

答案 2 :(得分:0)

也许你想要as.raw(65)代替65(十进制)是41(十六进制)

 > as.hexmode(65)
[1] "41"

至于编码,您可以在Hadoop流中使用二进制数据吗?