我在Windows操作系统下有一个压缩的二进制文件,我试图用R读取.到目前为止,它使用unz()函数与readBin()函数结合使用.
> bin.con <- unz(zip_path, file_in_zip, open = 'rb')
> readBin(bin.con,
"double",
n = byte_chunk,
size = 8L,
endian = "little")
> close(bin.con)
Run Code Online (Sandbox Code Playgroud)
其中zip_path是zip文件的路径,file_in_zip是zip文件中要读取的文件名,byte_chunk是我想要读取的字节数.
在我的用例中,readBin操作是循环的一部分,并逐渐读取整个二进制文件.但是,我很少想阅读所有内容,而且我经常知道我想要阅读的部分.不幸的是,readBin没有跳过前n个字节的start/skip参数.因此,我尝试用seek()有条件地替换readBin(),以跳过不需要的部分的实际读取.
当我尝试这个时,我收到一个错误:
> bin.con <- unz(zip_path, file_in_zip, open = 'rb')
> seek(bin.con, where = bytes_to_skip, origin = 'current')
Error in seek.connection(bin.con, where = bytes_to_skip, origin = "current") :
seek not enabled for this connection
> close(bin.con)
Run Code Online (Sandbox Code Playgroud)
到目前为止,我没有找到解决此错误的方法.类似的问题可以在这里找到(遗憾的是没有令人满意的答案):
互联网上的提示建议将open ='r'参数添加到unz()或完全删除open参数,但这仅适用于非二进制文件(因为默认为'r').人们还建议首先解压缩文件,但由于文件很大,这实际上是不可能的.
有没有办法解决二进制压缩文件或读取字节偏移量(可能通过Rcpp包使用C++)?
更新:
进一步的研究似乎表明zip文件中的seek()不是一个容易的问题.这个问题提出了一个c ++库,它最多可以使用粗略的搜索.这个Python问题表明,由于zip的实现方式,完全不可能进行精确搜索(尽管它与粗搜索方法不矛盾).
这是一个可能对你有用的黑客攻击.这是一个假的二进制文件:
writeBin(as.raw(1:255), "file.bin")
readBin("file.bin", raw(1), n = 16)
# [1] 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10
Run Code Online (Sandbox Code Playgroud)
这是生成的zip文件:
zip("file.zip", "file.bin")
# adding: file.bin (stored 0%)
readBin("file.zip", raw(1), n = 16)
# [1] 50 4b 03 04 0a 00 02 00 00 00 7b ab 45 4a 87 1f
Run Code Online (Sandbox Code Playgroud)
这使用临时中间二进制文件.
system('sh -c "unzip -p file.zip file.bin | dd of=tempfile.bin bs=1c skip=5c count=4c"')
# 4+0 records in
# 4+0 records out
# 4 bytes copied, 0.00044964 s, 8.9 kB/s
file.info("tempfile.bin")$size
# [1] 4
readBin("tempfile.bin", raw(1), n = 16)
# [1] 06 07 08 09
Run Code Online (Sandbox Code Playgroud)
这种方法将处理存储的二进制数据大小的"费用"抵消到R中的shell /管道.
这适用于win10,R-3.3.2.我使用的是dd
从混帐的Windows(版本2.11.0.3,虽然2.11.1可用),并且unzip
和sh
来自RTools.
Sys.which(c("dd", "unzip", "sh"))
# dd
# "C:\\PROGRA~1\\Git\\usr\\bin\\dd.exe"
# unzip
# "c:\\Rtools\\bin\\unzip.exe"
# sh
# "c:\\Rtools\\bin\\sh.exe"
Run Code Online (Sandbox Code Playgroud)