如何打印目录中文件的内容但忽略在写入模式下打开的文件?

问题描述 投票:0回答:1

我有一个goroutine,定期检查目录中的新文件,然后打印文件的内容。然而,还有另一个goroutine创建一个文件,将内容写入其中,然后保存文件。

如何忽略目录中以WRITE模式打开的文件?

示例代码:

for {
 fileList, err := ioutil.ReadDir("/uploadFiles")
  if err != nil {
     log.Fatal(err)
     continue
  }

 for _, f := range fileList {
      log.Println("File : ", f.Name())
      go printContents(f.Name())
 }

 time.Sleep(time.Second * 5)
}

在printContents goroutine中,我想忽略在WRITE模式下打开的文件。

go
1个回答
0
投票

这不是它的完成方式。

在我的头脑中,我可以想到这些选项:

  • 如果两个goroutine都在同一个程序中工作,那么几乎没有问题:让“producer”goroutine将已经完成修改的文件的名称注册到某个注册表中,并使该“注册表”中的“consumer”goroutine读取(和删除) 。 在最简单的情况下,可以是缓冲通道。 如果生产者的工作速度比消费者快得多,并且您不希望由于某种原因阻止前者,那么受互斥锁保护的切片将适合该账单。
  • 如果goroutine在同一台机器上的不同进程中工作,但您控制两个程序,则让生产者进程通过任何合适的IPC将相同的数据传递给使用者进程。 做什么方法IPC更好取决于流程如何启动,交互等。 有各种各样的选择。
  • 如果您控制两个进程但不想在它们之间混淆IPC(也有原因),那么让生产者遵循如何编写文件的最佳实践(稍后会详细介绍),并让消费者使用任何文件系统监视工具,用于报告生成器生成后创建(“出现”)哪些文件。你可以从github.com/fsnotify/fsnotify开始。 为了正确地写入文件,生产者必须将其数据写入临时文件 - 即位于同一目录但具有文件名的文件,该文件很好地理解为表明文件尚未完成 - 例如, “.foobar.data.part”或“foobar.data.276gd14054.tmp”可以写“foobar.data”。 (存在其他方法,但这个方法足以开始。) 文件准备好后,生产者必须将文件从其临时名称重命名为“正确”的最终名称。这个操作在所有敏感的操作系统/文件系统上都是原子操作,并使文件从消费者的PoV原子上“弹出存在”。例如,inotify on Linux generates an event of type "moved to" for such an appearance。 如果你不想自己做正确的事,github.com/dchest/safefile是一个很好的跨平台开始。 正如您所看到的,使用这种方法,您知道文件只是根据报告显示的事实完成的。
  • 如果你不控制制片人,你可能需要求助于猜测。 simpest再次监视文件系统的事件 - 但这次是“文件更新”事件,而不是“文件创建”事件。对于报告为已更新的每个文件,您必须记住该事件的时间戳,并且当经过一定时间后,您可以声明该文件由生产者完成。 IMO这种方法是最糟糕的,但如果你没有更好的选择,那至少是一些东西。
© www.soinside.com 2019 - 2024. All rights reserved.