在没有关闭的情况下使流无效

时间:2016-02-01 18:14:52

标签: java file-io file-descriptor fileinputstream finalizer

这是anonymous file streams reusing descriptors

的后续内容

根据我之前的问题,我不能依赖这样的代码(恰好在JDK8中工作,暂时):

md5()

但是,为了防止意外错误和自我文档的形式,我想在完成使用它之后使每个文件流无效 - 而不关闭底层文件描述符。

每个FileInputStream都是独立的,其定位由RandomAccessFile控制。我共享相同的FileDescriptor以防止因多次打开相同路径而引起的任何竞争条件。当我完成一个FileInputStream时,我想使它无效,以便在使用第二个FileInputStream(这会导致第二个FileInputStream跳过数据)时不可能意外地从中读取它。

我该怎么做?

注释:

  • 我使用的库需要与java.io。*
  • 兼容
  • 如果你建议一个库(如果可能的话,我更喜欢内置的java语义),它必须通常可用(打包)用于linux(主要目标)并可在Windows上使用(实验目标)
  • 但是,Windows支持并非绝对必要

编辑:在回复评论时,这是我的工作流程:

RandomAccessFile  r = new RandomAccessFile(...);

FileInputStream f_1 = new FileInputStream(r.getFD());
                      // some io, not shown
                f_1 = null;

                f_2 = new FileInputStream(r.getFD());
                      // some io, not shown
                f_2 = null;

                f_3 = new FileInputStream(r.getFD());
                    // some io, not shown
                f_3 = null;

2 个答案:

答案 0 :(得分:2)

纯Java解决方案可能是创建一个转发装饰器,它检查每个方法调用是否验证了流。对于InputStream,此装饰器可能如下所示:

public final class CheckedInputStream extends InputStream {
  final InputStream delegate;
  boolean validated;

  public CheckedInputStream(InputStream stream) throws FileNotFoundException {
    delegate = stream;
    validated = true;
  }

  public void invalidate() {
    validated = false;
  }

  void checkValidated() {
    if (!validated) {
      throw new IllegalStateException("Stream is invalidated.");
    }
  }

  @Override
  public int read() throws IOException {
    checkValidated();
    return delegate.read();
  }

  @Override
  public int read(byte b[]) throws IOException {
    checkValidated();
    return read(b, 0, b.length);
  }

  @Override
  public int read(byte b[], int off, int len) throws IOException {
    checkValidated();
    return delegate.read(b, off, len);
  }

  @Override
  public long skip(long n) throws IOException {
    checkValidated();
    return delegate.skip(n);
  }

  @Override
  public int available() throws IOException {
    checkValidated();
    return delegate.available();
  }

  @Override
  public void close() throws IOException {
    checkValidated();
    delegate.close();
  }

  @Override
  public synchronized void mark(int readlimit) {
    checkValidated();
    delegate.mark(readlimit);
  }

  @Override
  public synchronized void reset() throws IOException {
    checkValidated();
    delegate.reset();
  }

  @Override
  public boolean markSupported() {
    checkValidated();
    return delegate.markSupported();
  }
}

您可以像以下一样使用它:

CheckedInputStream f_1 = new CheckedInputStream(new FileInputStream(r.getFD()));
                      // some io, not shown
                   f_1.invalidate();

                   f_1.read(); // throws IllegalStateException

答案 1 :(得分:0)

在unix下,您通常可以通过dup文件描述符来避免此类问题。

由于java不提供这样的功能,因此一个选项将是暴露它的本机库。 jnr-posix就是这样做的。另一方面,jnr依赖于比原始问题更多的jdk实现属性。