Java 锁定未来文件

Java 锁定未来文件,java,file,locking,file-locking,Java,File,Locking,File Locking,因此,我有一个Samba文件服务器,我的Java应用程序需要在该服务器上编写一些文件。问题是,还有另一个php应用程序(如果php脚本被认为是应用程序的话)正在积极地从同一目录中提取新文件 有时,php脚本会在我的Java应用程序将文件完全写入磁盘之前提取该文件。这里有一点ascii艺术可以帮助我直观地看到我目前拥有的(但不起作用): 桑巴舞分享 /foo(我的java应用程序将文件放在这里) /bar(php正在拉取的目录) 我目前正在做的是,当文件满足某些标准时,它会被移动到/bar,然后被

因此,我有一个Samba文件服务器,我的Java应用程序需要在该服务器上编写一些文件。问题是,还有另一个php应用程序(如果php脚本被认为是应用程序的话)正在积极地从同一目录中提取新文件

有时,php脚本会在我的Java应用程序将文件完全写入磁盘之前提取该文件。这里有一点ascii艺术可以帮助我直观地看到我目前拥有的(但不起作用):

桑巴舞分享

/foo
(我的java应用程序将文件放在这里)

/bar
(php正在拉取的目录)

我目前正在做的是,当文件满足某些标准时,它会被移动到
/bar
,然后被php拾取以进行更多处理。我尝试过不同的方法,比如在调用
renameTo
之前将文件设置为不可写和不可读

我看了一下
FileLock
s,但它似乎无法锁定未来的文件。所以我想知道我这里有什么可能性?在完全编写文件之前,我可以使用什么来锁定文件,而不必接触php(因为,好吧,它是php,我现在没有修改它的权利)

谢谢

编辑1

如果php脚本在任何方面都有帮助的话,我已经对它的实际用途有了一些了解

它在循环中读取目录文件(使用而不睡眠)

一旦找到除“.”和“.”之外的文件名,它就会调用,这就是它失败的原因,因为文件没有完全写入磁盘(或者甚至没有写入磁盘,因为Java代码可能甚至没有时间在
readdir
file\u get\u contents
之间写入文件)

编辑2


这个Java应用程序正在替换一个旧的php脚本。当他们实现它时,他们遇到了与我现在遇到的相同的问题。他们通过在
/bar/tmp
中编写新文件(使用
文件内容
)然后使用将其移动到bar(看起来重命名应该是原子的)来解决这个问题。到目前为止,它工作得很好。我不能也不会相信Java不能比php做得更好…

我认为这是因为读取锁是共享的(多个进程可以对同一个文件应用读取锁并一起读取)

一种方法是,当
/bar/file1
尚未完成复制时,创建一个单独的临时锁定文件(例如:
/bar/file1.lock


然后修改php代码,确保文件在读取之前没有被锁定。

您提到您已经尝试过,但请记住javadoc中关于该方法的免责声明:

锁是否确实阻止另一个程序访问 锁定区域的内容取决于系统,因此 未指定。某些系统的本机文件锁定功能是 仅仅是建议,这意味着项目必须合作遵守 已知的锁定协议,以保证数据完整性

您还提到您正在使用,这也有一些注意事项(在javadoc中提到):

此方法行为的许多方面都是固有的 平台相关:重命名操作可能无法移动 从一个文件系统到另一个文件系统,它可能不是原子的,而且 可能不会成功

尝试使用
原子移动
选项,而不是
File.renameTo
。如果无法进行原子移动,您必须捕获并可能返回到其他解决方法

您可以使用创建硬链接,然后删除原始目录条目(在本例中,
/foo/myFile

如果不这样做,一个不需要修改PHP的简单解决方法是使用shell命令或系统调用将文件从/foo移动到/bar。例如,您可以使用
ProcessBuilder
调用
mv
,或者调用
ln
在/bar中创建符号链接或硬链接。您可能仍然有相同的问题如果/foo和/bar在不同的文件系统上,则使用
mv
lem


如果您在服务器上拥有root权限,您也可以尝试实现强制文件锁定。我在C中找到了一个,但是您可以从Java调用C程序,或者使用(或者JNI,如果您想惩罚自己的话)将示例改编为Java.

我也有同样的想法,但问题不幸地指出,修改PHP不是一个选项。/foo和/bar在同一个文件系统上吗?ATOMIC_MOVE选项没有任何不同。文件在完全写入磁盘之前仍在被提取。ProcessBuilder说文件/路径不存在,我遇到了奇怪的异常(错误=2),在控制台中粘贴准确的命令行是可行的,但是…当你说在控制台中粘贴命令行是可行的时,你的意思是它执行了,还是它也解决了PHP脚本拾取不完整文件的问题?请添加ProcessBuilder代码和堆栈跟踪到这个问题。它执行了,到目前为止,它也解决了问题我将在这个问题上添加更多的上下文。您确定Java代码在您尝试移动文件之前完成了文件的编写(并调用close())吗?我假设是的。我正在使用