我想安全地测试一个文件(例如,名为test.docx)是否使用R打开.

这个answer提出了一个解决方案,但相关的注释抱怨它损坏了文件.我也发现它损坏了文件,当我在test.docx上使用它时,结果是空白的docx.

使用rmarkdown(称为test.Rmd)生成示例docx文件的代码:

---
title: "test"
output: 
  officedown::rdocx_document:
---


# heading 1

# heading 2

渲染调用:

library(bookdown)
library(officedown)
library(officer)
rmarkdown::render('test.Rmd', 
                  output_format = 'rdocx_document')

使用建议的解决方案测试是否打开:

file.opened <- function(path) {
  suppressWarnings(
    "try-error" %in% class(
      try(file(path, 
               open = "w"), 
          silent = TRUE
      )
    )
  )
}
file.opened("test.docx")
# [1] FALSE

它正确地返回FALSE,因为我还没有打开文件,但是文件现在已经被编辑并且是空白的(文件大小减少到0).

测试它是否打开的安全方法是什么?

谢谢

推荐答案

正如哈德利·韦翰在《Advanced R》中所写:

可以保存try()的结果,并根据代码成功或失败执行不同的操作,但不建议这样做.相反,最好使用tryCatch().

下面是我编写此函数的方式:

is_file_open <- function(path, mode = "r+b") {
  tryCatch(
    {
        con  <- suppressWarnings(file(path, open = mode))
        on.exit(close(con))
        FALSE
    },
    error = function(e) TRUE
  )
}

我们可以用"r+b"模式打开文件.从file()docs开始:

"r+" "r+b":开放阅读和写作.

因为docx是二进制的,所以我们应该使用b,尽管我认为如果您不向文件写入数据,这并不重要.这将提供正确的输出,并且不会删除文件的内容.

此外,使用前面的函数,如果您运行几次,然后运行showConnections(),它将打印类似Warning message: In .Internal(gc(verbose, reset, full)) :closing unused connection 4 (test.docx)的内容.我们可以通过在退出函数时显式关闭连接来避免这种情况.

# With the file open in MS Word
is_file_open("test.docx")
# [1] TRUE

# With the file not open
is_file_open("test.docx")
# [1] FALSE

更好的功能

然而,这种is_file_open()方法的一个问题是,如果遇到任何错误,它将返回TRUE.在这种情况下,这可能不是问题,但您不能实际使用该函数来可靠地测试文件是否打开.

我觉得最好是有这样一个功能:

can_write_to_file <- function(path, mode = "r+b") {
    if(!file.exists(path)) {
        warning("The file does not exist. Checking if it can be created.")
        tryCatch(
            {   
                # Check if we can write to a non-existent file
                close(suppressWarnings(file(path, open = "w")))
                # If we can then delete the empty file
                unlink(path)
                return(TRUE)
            },
            error = function(e) return(FALSE)
        )
    }
  # Check whether an existing file can currently be written to
  tryCatch(
    {
        close(suppressWarnings(file(path, open = mode)))
        TRUE
    },
    error = function(e) FALSE
  )
}

这就是用户对函数名的期望.

R相关问答推荐

如何创建构成多个独立列条目列表的收件箱框列?

列出用m n个值替换来绘制n个数字的所有方法(i.o.w.:R中大小为n的集合的所有划分为m个不同子集)

使用tidyverse / Mutate的存款账户余额

使用R中的Shapetime裁剪格栅文件

矩阵%*%矩阵中的错误:需要数字/复杂矩阵/向量参数

过滤器数据.基于两列的帧行和R中的外部向量

gt()从gt为相同内容的单元格 colored颜色 不同?

在另存为PNG之前隐藏htmlwidget绘图元素

提取第一个下划线和最后一个下划线之间的任何内容,例外情况除外

哪一行和行和 Select 特定行,但是考虑到Nas

`夹心::vcovCL`不等于`AER::tobit`标准错误

创建列并对大型数据集中的特定条件进行成对比较的更高效程序

使用ggplot2中的sec_axis()调整次轴

如何阻止围堵地理密度图?

以任意顺序提取具有多个可能匹配项的组匹配项

是否有一个R函数可以输出在输入的字符向量中找到的相应正则表达式模式?

如何在不使用SHINY的情况下将下拉滤镜列表添加到ggploy?

将日期列从字符转换为日期得到的结果是NAS

如何根据顺序/序列从数据框中排除值

在R中查找多列中的字符串