代码之家  ›  专栏  ›  技术社区  ›  Some Name

爪哇中的重复文件通道

  •  0
  • Some Name  · 技术社区  · 6 年前

    我们可以打开一个简单的频道 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 转单程票 插座通道 .

    1 回复  |  直到 6 年前
        1
  •  2
  •   apangin    6 年前

    Java没有用于复制文件通道的公共API。

    但是,不需要复制filechannel来同时写入多个socketchannels。

    1. FileChannel.transferTo 可以在多个线程中并发使用(至少在类Unix系统上)。正如javadoc所说,这个方法不会修改通道的位置。
    2. FileChannel.read(ByteBuffer, long) 也可以在Unix上并发使用。在Windows上,此方法保持通道的位置锁定。
    3. 或者,也可以使用 FileChannel.map . 这些mappedByteBuffers可以同时使用。

    如果你还想打电话 dup 从Java(虽然我不建议这样做),您可以使用反射滥用私有API:

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