为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
素胚勾勒不出你 2023-05-15 15:10:27
我有一个 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 模式打开的文件。
查看完整描述

1 回答

?
红糖糍粑

TA贡献1815条经验 获得超6个赞

事情不是这样的。

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

  • 如果两个 goroutine 都在同一个程序中工作,那么问题不大:让“生产者”goroutine 将其已完成修改的文件的名称注册到某个注册表中,并让“消费者”goroutine 从该注册表中读取(和删除) .

    在最简单的情况下,它可能是一个缓冲通道。

    如果生产者的工作速度比消费者快得多,并且您不想出于某种原因阻止前者,那么由互斥锁保护的切片将符合要求。

  • 如果 goroutines 在同一台机器上的不同进程中工作,但您控制两个程序,则让生产者进程通过任何合适的 IPC 将相同的数据传递给消费者进程。

    执行 IPC 的哪种方法更好取决于进程如何启动、交互等。

    有多种选择。

  • 如果您控制两个进程但不想弄乱它们之间的 IPC(也有原因),那么让生产者遵循关于如何编写文件的最佳实践(稍后会详细介绍),并让消费者使用任何文件系统监控工具,用于报告生产者生成(“出现”)哪些文件。你可以从github.com/fsnotify/fsnotify.

    为了正确地写入文件,生产者必须将其数据写入临时文件——即位于同一目录中但具有易于理解的文件名以指示该文件尚未完成的文件——例如, “.foobar.data.part”或“foobar.data.276gd14054.tmp”可以写入“foobar.data”。(存在其他方法,但这个方法足以作为开始。)

    一旦文件准备就绪,制作者必须将文件从其临时名称重命名为其“正确的”最终名称。此操作在所有合理的操作系统/文件系统上都是原子的,并使文件从消费者的 PoV 原子地“跳入存在状态”。例如,inotify在 Linux 上为这样的出现生成一个类型为“moved to”的事件。

    如果您不想自己做正确的事情,github.com/dchest/safefile这是一个很好的跨平台开始。

    正如您所看到的,通过这种方法,您知道文件已经完成,仅从它被报告到已经出现的事实。

  • 如果您不控制生产者,您可能需要求助于猜测。

    最简单的是再次监视文件系统的事件——但这次是“文件更新”事件,而不是“文件创建”事件。对于报告为已更新的每个文件,您必须记住该事件的时间戳,并且当经过一定时间后,您可以声明该文件是由制作者完成的。

    IMO 这种方法是最糟糕的,但如果你没有更好的选择,它至少是一种选择。


查看完整回答
反对 回复 2023-05-15
  • 1 回答
  • 0 关注
  • 109 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信