即使目标文件已经存在,如何在 Java 中自动重命名文件?
我有一组机器,每台机器都运行一个 Java 应用程序。
这些 Java 应用程序需要同时访问唯一的 resource.txt
文件。
我需要在 Java 中自动将 temp.txt
文件重命名为 resource.txt
,即使 resource.txt
已经存在。
删除 resource.txt
并重命名 temp.txt
不起作用,因为它不是原子的(它会创建一个很小的时间范围,而 resource.txt
不会不存在)。
而且应该是跨平台的...
I have a cluster of machines, each running a Java app.
These Java apps need to access a unique resource.txt
file concurrently.
I need to atomically rename a temp.txt
file to resource.txt
in Java, even if resource.txt
already exist.
Deleting resource.txt
and renaming temp.txt
doesn't work, as it's not atomic (it creates a small timeframe where resource.txt
doesn't exist).
And it should be cross-platform...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
对于 Java 1.7+,请使用
java.nio.file.Files.move(Path source, Path target, CopyOption... options)
以及 CopyOptions“REPLACE_EXISTING”和“ATOMIC_MOVE”。有关详细信息,请参阅 API 文档。
例如:
For Java 1.7+, use
java.nio.file.Files.move(Path source, Path target, CopyOption... options)
with CopyOptions "REPLACE_EXISTING" and "ATOMIC_MOVE".See API documentation for more information.
For example:
在Linux(我相信Solaris和其他UNIX操作系统)上,Java的File.renameTo()方法将覆盖目标文件(如果存在),但在Windows下情况并非如此。
为了跨平台,我认为您必须对resource.txt使用文件锁定,然后覆盖数据。
默认情况下,Linux 使用自愿锁定,而 Windows 则强制执行。 也许您可以检测操作系统,并在 UNIX 下使用 renameTo() 以及 Windows 的一些锁定代码?
还有一种方法可以在 Linux 下对特定文件打开强制锁定,但它有点晦涩难懂。 您必须正确设置模式位。
On Linux (and I believe Solaris and other UNIX operating systems), Java's File.renameTo() method will overwrite the destination file if it exists, but this is not the case under Windows.
To be cross platform, I think you'd have to use file locking on resource.txt and then overwrite the data.
Linux, by default, uses voluntary locking, while Windows enforces it. Maybe you could detect the OS, and use renameTo() under UNIX with some locking code for Windows?
There's also a way to turn on mandatory locking under Linux for specific files, but it's kind of obscure. You have to set the mode bits just right.
这是相关的讨论: https://bugs.java.com/bugdatabase/view_bug ?bug_id=4017593
Here is a discussion that relates: https://bugs.java.com/bugdatabase/view_bug?bug_id=4017593
正如此处所述,它看起来像Windows 操作系统甚至不支持旧版本的原子文件重命名。 您很可能必须使用一些手动锁定机制或某种事务。 为此,您可能需要查看 apache commons transaction 包。
As stated here, it looks like the Windows OS doesn't even support atomic file rename for older versions. It's very likely you have to use some manual locking mechanisms or some kind of transactions. For that, you might want to take a look into the apache commons transaction package.
如果这应该是跨平台的,我建议有两个选择:
If this should be cross-platform I suggest 2 options:
如果重命名的目的是动态替换resource.txt并且您可以控制所有涉及的程序,并且替换的频率不高,您可以请执行下列操作。
要打开/读取文件:
要替换文件:
这将确保您的所有读者始终找到有效的文件。
但是,更简单的方法是简单地尝试循环打开,例如:
If the purpose of the rename is to replace resource.txt on the fly and you have control over all the programs involved, and the frequency of replacement is not high, you could do the following.
To open/read the file:
To replace the file:
Which will ensure all your readers always find a valid file.
But, easier, would be to simply try your opening in a loop, like:
在重命名文件之前,您可能会通过在文件上建立文件通道锁(并在获得锁定后删除要覆盖的文件)来获得一些牵引力。
-r
You might get some traction by establishing a filechannel lock on the file before renaming it (and deleting the file you're going to overwrite once you have the lock).
-r
我用一个简单的重命名函数来解决。
调用:
checkName 函数检查是否存在。
如果退出,则将两个括号 (1) 之间的数字连接到文件名的末尾。
功能:
编辑:它仅适用于 pdf。 如果您需要其他文件,请替换 .pdf 或为其创建扩展参数。
注意:如果文件在方括号“(”之间包含其他数字,则可能会弄乱您的文件名。
I solve with a simple rename function.
Calling :
The checkName function checks if exits.
If exits then concat a number between two bracket (1) to the end of the filename.
Functions:
EDIT: Its only works for pdf. If you want other please replace the .pdf or create an extension paramter for it.
NOTE: If the file contains additional numbers between brackets '(' then it may mess up your file names.