- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我注意到 java.io
和 java.nio
随机访问文件的实现在 FileLocks
方面略有不同。得到处理。
似乎(在 Windows 上)java.io
为您提供强制文件锁定,而 java.nio
分别在请求时为您提供建议文件锁定。强制文件锁意味着锁适用于所有进程,建议适用于遵循相同锁定协议(protocol)的行为良好的进程。
如果我运行以下示例,我可以手动删除*.nio
文件,而*.io
文件拒绝删除。
import java.io.*;
import java.lang.management.ManagementFactory;
import java.nio.*;
import java.nio.channels.*;
import java.nio.file.*;
public class NioIoLock {
public static void main(String[] args) throws IOException, InterruptedException {
String workDir = System.getProperty("user.dir");
FileChannel channelIo, channelNio;
FileLock lockIo, lockNio;
// use io
{
String fileName = workDir
+ File.separator
+ ManagementFactory.getRuntimeMXBean().getName()
+ ".io";
File lockFile = new File(fileName);
lockFile.deleteOnExit();
RandomAccessFile file = new RandomAccessFile(lockFile, "rw");
channelIo = file.getChannel();
lockIo = channelIo.tryLock();
if (lockIo != null) {
channelIo.write(ByteBuffer.wrap("foobar".getBytes("UTF-8")));
}
}
// use nio
{
Path workDirPath = Paths.get(workDir);
Path file = workDirPath.resolve(
Paths.get(ManagementFactory.getRuntimeMXBean().getName() + ".nio"));
// open/create test file
channelNio = FileChannel.open(
file, StandardOpenOption.READ, StandardOpenOption.WRITE,
StandardOpenOption.CREATE, StandardOpenOption.DELETE_ON_CLOSE);
// lock file
lockNio = channelNio.tryLock();
if (lockNio != null) {
channelNio.write(ByteBuffer.wrap("foobar".getBytes("UTF-8")));
}
}
// do not release locks for some time
Thread.sleep(10000);
// release io lock and channel
if (lockIo != null && lockIo.isValid()) {
lockIo.release();
}
channelIo.close();
// release nio lock and channel
if (lockNio != null && lockNio.isValid()) {
lockNio.release();
}
channelNio.close();
}
}
这是有原因的吗?这两者是否被视为替代品,或者它们是否意味着无限期共存?
最佳答案
TL;DR: 这与锁无关,与文件打开方式有关。您在 io
中看到的是在 Windows 2000 之前 Windows 可以做的最好的事情,即使文件以只读方式打开它也能做到这一点——无法删除该文件。您在 nio
中看到的是使用自 Windows 2000 以来引入的新功能的改进,但如果您愿意,您仍然可以在 nio
中使用旧行为。决定不将该功能移植到 io
的功能中。
全文:我删除了所有与锁定(见下文)以及写入文件相关的代码,它的工作原理与您的代码完全相同;但是,我还发现,如果您在打开“nio” channel 时指定 ExtendedOpenOption.NOSHARE_DELETE
,那么当您尝试删除任何两个文件时的行为是相同的(在代码中取消注释并尝试)。还找到了 this question,它有一些解释,不确定是否有帮助。
import java.io.*;
import java.lang.management.ManagementFactory;
import java.nio.*;
import java.nio.channels.*;
import java.nio.file.*;
public class NioIoLock {
public static void main(String[] args)
throws IOException, InterruptedException {
String workDir = System.getProperty("user.dir");
FileChannel channelIo, channelNio;
FileLock lockIo, lockNio;
// use io
{
String fileName = workDir + File.separator
+ ManagementFactory.getRuntimeMXBean().getName() + ".io";
File lockFile = new File(fileName);
lockFile.deleteOnExit();
RandomAccessFile file = new RandomAccessFile(lockFile, "rw");
channelIo = file.getChannel();
}
// use nio
{
Path workDirPath = Paths.get(workDir);
Path file = workDirPath.resolve(Paths
.get(ManagementFactory.getRuntimeMXBean().getName() + ".nio"));
// open/create test file
channelNio = FileChannel.open(file, StandardOpenOption.READ,
StandardOpenOption.WRITE, StandardOpenOption.CREATE,
StandardOpenOption.DELETE_ON_CLOSE
/*, com.sun.nio.file.ExtendedOpenOption.NOSHARE_DELETE*/);
}
// do not release locks for some time
Thread.sleep(10000);
}
}
更新 1: 实际上,我仍然不知道这背后的基本原理,但机制很清楚:RandomAccessFile
构造函数最终从 method winFileHandleOpen 调用以下 native 代码io_util_md.c:
FD
winFileHandleOpen(JNIEnv *env, jstring path, int flags)
{
...
const DWORD sharing =
FILE_SHARE_READ | FILE_SHARE_WRITE;
... // "sharing" not updated anymore
h = CreateFileW(
pathbuf, /* Wide char path name */
access, /* Read and/or write permission */
sharing, /* File sharing flags */
NULL, /* Security attributes */
disposition, /* creation disposition */
flagsAndAttributes, /* flags and attributes */
NULL);
...
}
因此,FILE_SHARE_DELETE
标志未设置,您无法设置它。另一方面,调用 java.nio.channels.FileChannel.open(Path, OpenOption...)
eventually 会考虑这个标志:
private static FileDescriptor open(String pathForWindows,
String pathToCheck,
Flags flags,
long pSecurityDescriptor)
throws WindowsException
{
...
int dwShareMode = 0;
if (flags.shareRead)
dwShareMode |= FILE_SHARE_READ;
if (flags.shareWrite)
dwShareMode |= FILE_SHARE_WRITE;
if (flags.shareDelete)
dwShareMode |= FILE_SHARE_DELETE;
...
// open file
long handle = CreateFile(pathForWindows,
dwDesiredAccess,
dwShareMode,
pSecurityDescriptor,
dwCreationDisposition,
dwFlagsAndAttributes);
...
}
更新 2: 从 JDK-6607535 开始:
The suggestion to change the sharing mode is RFE 6357433. It would be great to do that but it may break existing applications (since the current behavior has existed since jdk1.0). Adding a special mode to RandomAccessFile to work around a Windows issues is probably not the right approach either. Also, there is some suggestion that this can help with the issue of deleting files that have a file mapping. This is not so, as a file mapping still prevents a file from being deleted. Anyway, for jdk7 we are working on a new file system API that will address some of the requirements here. The Windows implementation does the right thing so that opened files can be deleted.
另请参阅从那里引用的 JDK-6357433:
A customer has pointed out on the java.net forums that opening a file on Windows using a FileInputStream causes other processes to be unable to delete the file. This is intended behavior as the code is currently written, as the sharing flags specified during the opening of the file are FILE_SHARE_READ and FILE_SHARE_WRITE. See io_util_md.c, fileOpen. However, Windows 2000 supplies a new flag, FILE_SHARE_DELETE, which allows another process to delete the file while it is still open.
最后
WORK AROUND
For jdk7, the workaround is to use new file system API. So instead of new FileInputStream(f) and new FileOutputStream(f), use f.toPath().newInputStream() and f.toPath().newOutputStream().
关于java - 随机访问文件 FileLock : java. io 与 java.nio,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39293193/
我让随机数低于之前的随机数。 if Airplane==1: while icounter0: print "You have enoph fuel to get to New
是否可以生成 BigFloat 的随机数?类型均匀分布在区间 [0,1)? 我的意思是,因为 rand(BigFloat)不可用,看来我们必须使用 BigFloat(rand())为了那个结局。然而,
我正在尝试学习 Kotlin,所以我正在学习互联网上的教程,其中讲师编写了一个与他们配合良好的代码,但它给我带来了错误。 这是错误 Error:(26, 17) Kotlin: Cannot crea
是否有任何方法可以模拟 Collections.shuffle 的行为,而不使比较器容易受到排序算法实现的影响,从而保证结果的安全? 我的意思是不违反类似的契约(Contract)等.. 最佳答案 在
我正在创建一个游戏,目前必须处理一些math.random问题。 我的Lua能力不是那么强,你觉得怎么样 您能制定一个使用 math.random 和给定百分比的算法吗? 我的意思是这样的函数: fu
我想以某种方式让按钮在按下按钮时随机改变位置。我有一个想法如何解决这个问题,其中一个我在下面突出显示,但我已经认为这不是我需要的。 import javafx.application.Applicat
对于我的 Java 类(class),我应该制作一个随机猜数字游戏。我一直陷入过去几天创建的循环中。程序的输出总是无限循环,我不明白为什么。非常感谢任何帮助。 /* This program wi
我已经查看了涉及该主题的一些其他问题,但我没有在任何地方看到这个特定问题。我有一个点击 Web 元素的测试。我尝试通过 ID 和 XPath 引用它,并使用 wait.until() 等待它变得可见。
我在具有自定义类的字典和列表中遇到了该异常。示例: List dsa = (List)Session["Display"]; 当我使用 Session 时,转换工作了 10-20 次..然后它开始抛
需要帮助以了解如何执行以下操作: 每隔 2 秒,这两个数字将生成包含从 1 到 3 的整数值的随机数。 按下“匹配”按钮后,如果两个数字相同,则绿色标签上的数字增加 1。 按下“匹配”按钮后,如果两个
void getS(char *fileName){ FILE *src; if((src = fopen(fileName, "r")) == NULL){ prin
如果我有 2 个具有以下字段的 MySQL 数据库... RequestDB: - Username - Category DisplayDB: - Username - Category
我有以下语句 select random() * 999 + 111 from generate_series(1,10) 结果是: 690,046183290426 983,732229881454
我有一个使用 3x4 CSS 网格构建的简单网站。但出于某种原因,当我在 chrome“检查”中检查页面时,有一个奇怪的空白 显然不在我的代码中的标签。 它会导致网站上出现额外的一行,从而导致出现
我有两个动画,一个是“过渡”,它在悬停时缩小图像,另一个是 animation2,其中图像的不透明度以周期性间隔重复变化。 我有 animation2 在图像上进行,当我将鼠标悬停在它上面时,anim
如图所示post在 C++ 中有几种生成随机 float 的方法。但是我不完全理解答案的第三个选项: float r3 = LO + static_cast (rand()) /( static_c
我正在尝试将类添加到具有相同类的三个 div,但我不希望任何被添加的类重复。 我有一个脚本可以将一个类添加到同时显示的 1、2 或 3 个 div。期望的效果是将图像显示为背景图像,并且在我的样式表中
我有一个基本上可以工作的程序,它创建由用户设置的大小的嵌套列表,并根据用户输入重复。 但是,我希望各个集合仅包含唯一值,目前这是我的输出。 > python3 testv.py Size of you
我正在尝试基于 C# 中的种子生成一个数字。唯一的问题是种子太大而不能成为 int32。有什么方法可以像种子一样使用 long 吗? 是的,种子必须很长。 最佳答案 这是我移植的 Java.Util.
我写这个函数是为了得到一个介于 0 .. 1 之间的伪随机 float : float randomFloat() { float r = (float)rand()/(float)RAN
我是一名优秀的程序员,十分优秀!