在R中,如何解读内存中的gzcon
?
背景:
我需要在内存中的.tar.gz文件上执行一些操作,重要的是永远不要将文件写入磁盘。该文件最初与curl_fetch_memory
一起下载,并生成与下面的示例数据类似的对象。
如果我在对象上执行untar(gzcon(rawConnection(res$content)))
,它会将tarfile中的数据写入磁盘,这是不可取的。
示例数据(包含名为.tar.gz
且内容为test.txt
的文件的hello world!
):
res <- structure(list(url = "sftp://vm@example.com:/test.tar.gz",
status_code = 0L, headers = raw(0), modified = structure(1479765215L, class = c("POSIXct",
"POSIXt")), times = structure(c(0, 0, 0, 0, 0.312, 0.312), .Names = c("redirect",
"namelookup", "connect", "pretransfer", "starttransfer",
"total")), content = as.raw(c(0x1f, 0x8b, 0x08, 0x00, 0xdf,
0x6c, 0x33, 0x58, 0x00, 0x03, 0xed, 0xce, 0x3d, 0x0a, 0xc2,
0x50, 0x10, 0xc4, 0xf1, 0xad, 0x73, 0x8a, 0xe7, 0x05, 0x64,
0x37, 0x79, 0xd9, 0x9c, 0x47, 0x30, 0x90, 0xe2, 0x49, 0x20,
0x59, 0x3f, 0x8e, 0xaf, 0x22, 0x42, 0x2a, 0x4d, 0x13, 0x44,
0xf8, 0xff, 0x9a, 0x29, 0x66, 0x8a, 0x89, 0x7e, 0x8e, 0x7d,
0xdc, 0x42, 0x36, 0xa4, 0x0f, 0xee, 0xf9, 0x99, 0xd6, 0xb5,
0xba, 0xcc, 0x17, 0x73, 0xb1, 0x46, 0x2d, 0xbb, 0x7b, 0xa3,
0xad, 0xa8, 0x69, 0xae, 0x3b, 0x49, 0xba, 0xe5, 0xa9, 0xb7,
0xf3, 0x1c, 0x87, 0x29, 0x25, 0xb9, 0x9c, 0x3e, 0xef, 0xbe,
0xf5, 0x7f, 0x6a, 0xe8, 0x4b, 0x19, 0xd3, 0x75, 0x9c, 0xca,
0x71, 0x57, 0x55, 0xbf, 0x7e, 0x03, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58,
0xeb, 0x0e, 0x02, 0xc4, 0x36, 0xca, 0x00, 0x28, 0x00, 0x00
))), .Names = c("url", "status_code", "headers", "modified",
"times", "content"))
答案 0 :(得分:1)
在untar上的extras = "O"
标志是否让您更接近您需要的东西?
例如,如果我创建了一个文件
echo "hello world" > afile
tar -cvf afile.tar.gz afile
然后我可以用
将它读到stdout(打印到R)untar('afile.tar.gz', compressed = 'gzip', extras = "-O")
我正在使用GNU Tar 1.29
答案 1 :(得分:1)
事实证明解析tarfiles并不困难。 utils:::untar2
的核心循环是实现内存中untar
工具的良好起点。基本上,tarfile具有以下结构:
+-----------------+-----------+-----------------+-----------+-~
| 512-byte header | file data | 512-byte header | file data |
+-----------------+-----------+-----------------+-----------+-~
在GNU manual for tar中更详细地描述了tar头格式,它由一些文件属性,幻数和校验和组成。
内存中解压缩工具的伪代码非常简单:
repeat {
parse tar header with file attributes
for each block in file {
write block to raw connection
}
write raw connection and file attributes to file object
add file to list
}
return list of files