Java 中的重复文件通道



我们可以打开一个像Files.newByteChannel(path)一样简单的频道,这将正常工作。问题是如果我想打开多个频道:

Channel chan1 = Files.newByteChannel(path);
Channel chan2 = Files.newByteChannel(path);

上面的例子通常效果不佳。考虑以下情况:

Channel chan1 = Files.newByteChannel(path); //OK
//Some other process moved path and created an new file with the path
Channel chan2 = Files.newByteChannel(path); //Damn!

出现争用条件。在 Linux 中,我们有类似dup的系统调用以及fcntl(F_DUPFD, int)

int fd == open(path);
int duplicated = fcntl(fd, F_DUPFD, fd);

这应该有效。

有没有办法在 Java 中做到这一点并避免编写JNI函数?

UPD:我想要副本的原因是我想同时将数据从一个文件传输到多个SocketChannel。因此,将单独的FileChannel转移到单个SocketChannel似乎是合理的。

Java 没有用于复制 FileChannels 的公共 API。

但是,无需复制文件通道即可同时写入多个套接字通道。

  1. FileChannel.transferTo可以在多个线程中同时使用(至少在类Unix系统上(。正如Javadoc所说,这种方法不会修改通道的位置。
  2. FileChannel.read(ByteBuffer, long)也可以在Unix上同时使用。在 Windows 上,此方法保持通道的位置锁定。
  3. 或者,可以使用FileChannel.map创建同一文件通道的多个字节缓冲区视图。这些 MappedByteBuffers 可以同时使用。

如果你仍然想从Java调用dup(尽管我不建议这样做(,你可以使用Reflection滥用私有API:

  • int sun.nio.fs.UnixNativeDispatcher.dup(int fd) 是 Unix 上dup的直接 Java 包装器;
  • long sun.nio.ch.FileDispatcherImpl.duplicateHandle(long handle)是Windows上DuplicateHandle的Java包装器。

最新更新