Я хочу безопасно проверить, открыт ли файл (например, с именем test.docx
) с помощью R
.
Этот ответ предлагает решение, но соответствующие комментарии жалуются, что оно повреждает файл. Я тоже обнаружил, что это повреждает файл и приводит к появлению пустого docx
, когда я использую его на test.docx
.
Код для создания примера файла docx
с использованием rmarkdown
(называемого test.Rmd
):
---
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()
:
"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
)
}
Это делает то, что пользователь ожидает от имени функции.