Linux 如何允许在 PDF 查看器中打开时修改 PDF?

Pra*_*r-M 15 ubuntu windows pdf

当我在 中处理图表时R,我尝试将它们直接输出到 PDF 中。例如,用于创建图形的代码如下。

library(ggplot2)
levels_fp = ggplot(data=df_forest_2,
    aes(x = levels,y=center, ymin=lower, ymax=upper))+
    geom_pointrange(aes(col=levels))+
    geom_hline(aes(fill=levels),yintercept =1, linetype=2)+
    xlab('Outcomes Evaluated')+ geom_errorbar(aes(ymin=lower, ymax=upper,col=levels),width=0.2,cex=1)+ 
    facet_wrap(~outcome,strip.position="top",nrow=1,scales = "free_x") + theme(
    axis.title = element_text(size = 18),
    axis.text = element_text(size = 14),
    legend.text = element_text(size = 16),
    legend.title = element_text(size = 16),
  
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(),
      
    axis.line = element_line(colour = "black"),
    legend.box.background = element_rect(),axis.text.x = element_blank(), strip.text.x = element_text(size = 14)
  ) + ylab("Odds Ratio")+labs(col="Interventions")

pdf(file="Forest_levels_2.pdf", width=12,height =12 ) 
levels_fp
dev.off()
Run Code Online (Sandbox Code Playgroud)

我感兴趣的是:假设我已经在 PDF 查看器中打开了 pdf(我从上一步输出,即Forest_levels_2.pdf)。然后,如果我再次运行代码,文件会得到输出并覆盖以前的 PDF,并且 PDF 查看器中的输出也会立即更改。

但是,如果我尝试在 Windows 中执行相同操作,即我已使用 PDF 查看器打开 PDF,然后尝试运行代码,则会出现以下错误 -->无法访问 pdf。为什么 Linux 中的行为有所不同(我使用的是 Ubuntu 20.04)?

添加 Windows 错误的输出

Error in pdf(file = "Forest_levels_2.pdf", width = 12, height = 12) : 
  cannot open file 'Forest_levels_2.pdf'

Run Code Online (Sandbox Code Playgroud)

为了删除一些变量,我尝试下载适用于Windows的Evince PDF查看器(Evince 2.32),然后在Windows中使用Evince打开PDF并再次进行相同的实验。

猜猜发生了什么!?!

我能够在 Windows 中成功修改打开的 PDF。Evince 在 Ubuntu 和 Windows 中的工作方式相同。所以可能,它也更依赖于 PDF 查看器的属性。

Ste*_*art 40

这是您使用的 PDF 查看器的功能。

我怀疑,PDF 查看器打开文件,然后读取/处理内容。它不必关闭文件,但可能会关闭。

接下来,它会设置一个inotify,这意味着如果有人写入文件,您的 PDF 查看器将收到通知。

当您写入文件时,您的 PDF 查看器收到一个信号,表明它正在查看的文件已更改。这使 PDF 查看器有机会重新阅读文件并重新处理内容。

类似的东西在 Windows 中是可能的,但您使用的 PDF 查看器根本没有实现。当您的 Windows PDF 查看器打开 PDF 时,默认情况下它会获得对 PDF 文件的独占访问权限,这将导致另一个程序在尝试打开文件进行写入时出错。查看器必须进行系统调用以明确放弃独占访问,以便以与 linux 版本类似的方式进行操作。


我发现了一篇关于文件锁定的有趣的维基百科文章。它说:

Windows 从 MS-DOS 系统继承了共享访问控制的语义,其中共享是在 MS-DOS 3.3 中引入的。因此,应用程序在打开文件时必须明确允许共享;否则,它在关闭之前对文件具有独占读取、写入和删除访问权限(允许其他类型的访问,例如检索文件属性的访问。)

它还说:

类 Unix 操作系统(包括 Linux 和 Apple 的 macOS)通常不会自动锁定打开的文件。

  • 后半部分是我心目中最重要的部分;默认情况下,Windows 会锁定打开的文件,这会导致问题中提到的错误。 (33认同)
  • 关于文件锁定的这一点相当重要。在大多数情况下,由于这种行为,您无法在 Windows 上替换打开的文件(这就是为什么您必须在 Windows 上每次操作系统更新时重新启动),但您几乎总是可以在类 UNIX 系统上这样做(可能即使文件被锁定,具体取决于具体情况)。 (8认同)
  • @ChrisH SumatraPDF 是一个用于 Windows 的 PDF 查看器,它不会锁定 PDF 文件(如果有兴趣的话)。 (5认同)
  • Adobe 阅读器行为是经过深思熟虑的设计选择:pdf 文件被锁定并且仅部分读入内存。这允许 Reader 处理非常大的 pdf 文件。另一方面,Evince 会将整个文件读入内存,这可能会在 RAM 不足的系统上产生问题。(从记忆中,虽然我记得来源似乎是可靠的:adobe 开发人员或类似的) (4认同)
  • 添加到 [@VisualMelon 的评论](https://unix.stackexchange.com/questions/606588/how-does-linux-allow-modifying-a-pdf-while-open-in-a-pdf-viewer#comment1132515_606592) ,SumatraPDF 与 RStudio 一起安装,因此它实际上可能已经在 OP 的系统上可用。SumatraPDF 是我个人的非锁定 PDF 查看器,用于在编辑 PDF 时查看它们(使用 R 或 LaTeX)。 (3认同)
  • @AustinHemmelgarn,...并且在 Unixen 上,如果有正在运行的进程打开它们,则文件的旧副本将继续使用。这意味着例如要更新 C 库,您仍然必须重新启动系统上的几乎每个进程才能让它们使用新版本。无论如何,这与重新启动非常接近。:) (2认同)