4

我正在尝试AsynchronousFileChannelJAVA 7 API 以异步方式写入文件,但是我找不到附加到文件的简单方法。

API 描述指出AsynchronousFileChannel不维护文件位置,您必须指定文件位置。这意味着您必须维护一个全局文件位置值。此外,这个全局状态应该是原子的,以便您正确递增。

有没有更好的方法来使用 进行更新AsynchronousFileChannel

另外,有人可以解释一下 API 中 Attachment 对象的用法吗?

public abstract <A> void write(ByteBuffer  src,
             long position,
             A attachment,
             CompletionHandler<Integer ,? super A> handler)

javadoc 说: attachment - 附加到 I/O 操作的对象;可以为空

这个附件对象有什么用?

谢谢!

4

2 回答 2

3

这个附件对象有什么用?

附件是您可以传递给完成处理程序的对象;将其视为提供背景信息的机会。你可以将它用于几乎任何你能想象到的事情,从日志记录到同步,或者只是简单地忽略它。

我正在尝试 AsynchronousFileChannel JAVA 7 API 以异步方式写入文件,但是我找不到附加到文件的简单方法。

异步通常有点棘手,附加到文件是一个固有的串行过程。也就是说,您可以并行执行,但您必须记录下一个缓冲区内容的附加位置。我想它可能看起来像这样(使用频道本身作为“附件”):

class WriteOp implements CompletionHandler<Integer, AsynchronousFileChannel> {
  private final ByteBuffer buf;
  private long position;

  WriteOp(ByteBuffer buf, long position) {
    this.buf = buf;
    this.position = position;
  }

  public void completed(Integer result, AsynchronousFileChannel channel) {
    if ( buf.hasRemaining() ) { // incomplete write
      position += result;
      channel.write( buf, position, channel, this );
    }
  }

  public void failed(Throwable ex, AsynchronousFileChannel channel) {
    // ?
  }
}

class AsyncAppender {
  private final AsynchronousFileChannel channel;
  /** Where new append operations are told to start writing. */
  private final AtomicLong projectedSize;

  AsyncAppender(AsynchronousFileChannel channel) throws IOException {
    this.channel = channel;
    this.projectedSize = new AtomicLong(channel.size());
  }

  public void append(ByteBuffer buf) {
    final int buflen = buf.remaining();
    long size;
    do {
      size = projectedSize.get();
    while ( !projectedSize.compareAndSet(size, size + buflen) );

    channel.write( buf, position, channel, new WriteOp(buf, size) );
  }
}
于 2015-07-23T15:28:54.827 回答
1

我刚刚使用了channel.size()作为位置。在我的情况下,文件没有被多个线程修改,只有一个线程打开并写入文件,这似乎工作到目前为止。

如果有人知道这是错误的做法,请插话。

于 2015-08-16T15:58:04.147 回答