检查文件是否为二进制

Check whether file is binary

我想要一个函数 is.binary 给出以下结果

tmp_vec=1:3

save(tmp_vec,file="temp_vec.RData")
write.csv(tmp_vec,"temp_vec.csv")

is.binary("temp_vec.RData")
#TRUE

is.binary("temp_vec.csv")
#FALSE

R有这样的功能吗? 我能想出的最佳解决方案是

is.binary=function(filename) {
  is_binary=TRUE
  #suppress warnings and try to read file with binary reader
  #if it throws an error, set is_binary to FALSE
  withCallingHandlers(expr=tryCatch(load(filename),
                                    error=function(err) is_binary<<-FALSE),
                      warning=function(w) invokeRestart("muffleWarning"))
  #since R loads the objects of the binary file into the memory, delete them
  #maybe this is unnecessary ... 
  #... I do not know how R handles memory of objects that go out of scope
  rm(list=ls()[ls()!="is_binary"])
  is_binary
}

显然,这个函数在处理大文件时效率不是很高。任何指向更好解决方案的指示?谢谢!

编辑:我在 Windows 机器上。

计算机上的所有文件都是二进制文件。例外是那些碰巧看起来像文本文件的文件。甚至那些可能具有实际正确读取文件所需的不同编码。

如果您只是想区分 save()write.csv() 的结果,最简单的检查方法是文件是否已压缩。默认情况下 save() 将压缩文件。您可以在文件中查找用于压缩的幻数。这是一种方法

is_compressed <- function(filename, magic.number=as.raw(c("0x1f","0x8b"))) {
    fh<-file(filename, "rb")
    on.exit(close(fh))
    magic <- readBin(fh, "raw", length(magic.number))
    if(length(magic) != length(magic.number)) return(FALSE)
    if(all(magic == magic.number)) return(TRUE)
    return (FALSE)
}

这只需要读取文件的两个字节而不是整个文件。一旦您知道它已被压缩,您就可以尝试寻找 rData 文件的幻数。这里有一个更完整的功能

is_rdata <- function(filename) {
    #check for magic number
    #https://github.com/wch/r-source/blob/b99d403f4b7337553acb2d2108c7a00e6c19f908/src/main/saveload.c#L1786

    fh <- if(!is_compressed(filename))
        file(filename, "rb")
    else {
        gzfile(filename, "rb")
    }
    on.exit(close(fh))


    magic <- rawToChar(readBin(fh, "raw", 5))
    if(nchar(magic)<5) return(FALSE)
    if(magic %in% c("RDA1\n","RDB1\n","RDX1\n","RDA2\n","RDB2\n","RDX2\n")) return(TRUE)
    return (FALSE)
}

我们可以用

进行测试
dd <- data.frame(a=1:4, b=letters[1:4])

save(dd, file="test1.file")
write.csv(dd, file="test2.file")

is_rdata("test1.file")
is_rdata("test2.file")

当然,如果您注意文件扩展名,这可能是识别文件的最简单方法。