java - 设置为 ReadDirectoryChangesW 打开的目录的最后修改时间

标签 java windows winapi createfile readdirectorychangesw

我有一个 Java 程序需要监视目录树的更改。我有使用 ReadDirectoryChangesW() 的 JNI 代码。目录打开方式如下:

HANDLE dirHandle = CreateFile(
    path, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
    OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL
);

然后我将 dirHandle 传递给 ReadDirectoryChangesW()。所有这些都很好。

问题是代码的其他部分(在 Java 端)使用 File.setLastModified() 来“触摸”文件或目录(将它们的时间戳更新为“现在”)。这通常有效;但是,当它尝试“触摸”使用 CreateFile() 打开的目录时失败。

为了查看实际发生的 Windows 错误,我查看了 File.setLastModified() 的 JDK 源代码,并在我自己的代码中重新实现了它,并添加了打印来自 GetLastError 的错误();错误是:

ERROR_SHARING_VIOLATION (error 32)
"The process cannot access the file because it is being used by another process."

WTF?这是相同的过程。我什至将 FILE_SHARE_READFILE_SHARE_WRITE 传递给 CreateFile()

有没有办法让它工作?

更多信息

JDK 中 File.setLastModified() 的 native 代码实现:

h = CreateFileW(pathbuf, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
                FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, 0);

如果我将第一个 0 更改为 FILE_SHARE_READ | FILE_SHARE_WRITE,一切正常。所以看起来 JDK 实现有点破。 :(

所以我的问题现在变成了:有没有一种方法可以使这项工作无需使用我自己的(重新)实现 File.setLastModified()

最佳答案

虽然在这种情况下错误消息有点误导,但您看到的是正常行为。

通过将 dwShareMode 设置为零打开目录,JDK 实际上是在请求独占访问,这将导致任何其他访问尝试失败并出现共享冲突错误。这同样适用于访问 来自其他流程和您自己的流程。

CreateFile documentation描述了 dwShareMode 参数:

If this parameter is zero and CreateFile succeeds, the file or device cannot be shared and cannot be opened again until the handle to the file or device is closed.

You cannot request a sharing mode that conflicts with the access mode that is specified in an existing request that has an open handle. CreateFile would fail and the GetLastError function would return ERROR_SHARING_VIOLATION.

看来您已经回答了自己的问题:您需要一个自定义 setLastModified 函数来指定 FILE_SHARE_READ | FILE_SHARE_WRITE 访问目录时。

关于java - 设置为 ReadDirectoryChangesW 打开的目录的最后修改时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1144635/

相关文章:

java - 移动 Java 位集

java - 如何使用 GSON 从此 JSON 文件获取文本?

c# - 在 Windows 10 中检测到布局循环,但在 Windows 8.1 中未检测到

linux - 在 Windows 10 上通过 Linux 子系统使用批处理文件?

c++ - DISK PERFORMANCE 结构的 Read Time 和 WriteTime 成员

perl - 如何使用 perl 在 Windows 10 上获取 OsVersion

Java按破折号分割

Java日期差异以毫秒为单位

java - 临时文件、单实例锁和进程终止 (Java)

c++ - 如何使用 "Stop Button"停止进程