我有一个需要监视目录树以进行更改的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_READ
和FILE_SHARE_WRITE
传递给CreateFile()
。
有没有办法让这项工作?
JDK中File.setLastModified()
的本机代码实现执行:
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()
的实现?
答案 0 :(得分:1)
虽然在这种情况下错误消息有点误导,但您所看到的是正常行为。
通过打开dwShareMode
设置为零的目录,JDK实际上要求独占访问,这将导致任何其他访问尝试失败并出现共享冲突错误。这同样适用于访问
来自其他流程和您自己的流程。
CreateFile
documentation描述了dwShareMode
参数:
如果此参数为零且CreateFile成功,则无法共享文件或设备,并且在关闭文件或设备的句柄之前无法再次打开文件或设备。
您无法请求与具有打开句柄的现有请求中指定的访问模式冲突的共享模式。
CreateFile
将失败,GetLastError
函数将返回ERROR_SHARING_VIOLATION
。
所以,您似乎已经回答了自己的问题:在访问目录时需要一个指定setLastModified
的自定义FILE_SHARE_READ | FILE_SHARE_WRITE
函数。