在不关闭的情况下使流无效 [英] Invalidate Stream without Closing

查看:182
本文介绍了在不关闭的情况下使流无效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是重复使用描述符的匿名文件流的后续处理



按照我以前的问题,我不能依赖这样的代码(现在在JDK8中正常工作):

  RandomAccessFile r = new RandomAccessFile(...); 

FileInputStream f_1 = new FileInputStream(r.getFD());
//一些io,未显示
f_1 = null;

f_2 = new FileInputStream(r.getFD());
//一些io,未显示
f_2 = null;

f_3 = new FileInputStream(r.getFD());
//一些io,未显示
f_3 = null;

然而,为了防止意外错误和作为自我记录的形式,我想使每个文件流在我完成使用后 - 不关闭底层文件描述符。

每个FileInputStream都是独立的,定位由RandomAccessFile控制。我共享相同的FileDescriptor,以防止由于多次打开相同路径而导致的任何竞争状况。当我完成一个FileInputStream时,我想使它无效,以便在使用第二个FileInputStream(这将导致第二个FileInputStream跳过数据)时无意中读取它。



我该怎么做?

$ p

如果你建议一个库(我更喜欢这个库),那么你可以使用这个库。内建的java语义,如果可能的话),它必须是通用的(打包)的Linux(主要目标)和可用于Windows(实验目标) 但是,windows的支持并不是绝对必要的



编辑:我的工作流程:
$ b $ pre $ RandomAccessFile r = new RandomAccessFile(String path,r);

int header_read;
int header_remaining = 4; //头部长度,最初为

byte [] ba = new byte [header_remaining];
ByteBuffer bb = new ByteBuffer.allocate(header_remaining); ((header_read = r.read(ba,0,header_remaining)> 0){
header_remaining - = header_read;
bb.put(ba,0,header_read );
}

byte [] header = bb.array();

//处理标题,未显示
//上面的RandomAccessFile (0);

FileInputStream f_1 = new FileInputStream(r.getFD()); $ b只读了一小部分,所以不需要缓冲

r.seek
$ b Library1Result result1 = library1.Main.entry_point(f_1)

//处理结果1,未显示
// Library1以大块读取InputStream,所以缓冲isn' (0)
$ b $ int read;
while((read = r。)
// invalidate f_1(this question)

r.seek读取(缓冲区,读取);
}

/ b读取(字节[4096]缓冲区))> 0& /上面的RandomAccessFile是以大块读取的,所以不需要缓冲
//在之前的编辑中,RandomAccessFile被用来创建一个FileI nputStream。显然这不是必需的,所以忽略

r.seek(0)

读者r_1 = new BufferedReader(new InputStreamReader(new FileInputStream(r.getFD())));

Library3Result result3 = library3.Main.entry_point(r_2)

//处理结果3,未显示
//我不确定Library3如何使用读取器,所以我提供了缓冲
// invalidate r_1(这个问题) - 奖金:释放缓冲区

r.seek(0);

FileInputStream f_2 = new FileInputStream(r.getFD());

Library1Result result1 = library1.Main.entry_point(f_2)

//处理结果1(重新分配),不显示
//是的, 'library1.Main.entry_point'* again * - 同样的注释适用于从
之前//无效f_2(这个问题)
//
//我被告知要小心如果缓冲的话,从相同的
//描述符打开多个流。这是非常模糊的。我假设,因为我只
//曾经和唯一使用任何流,此代码是安全的。
//


解决方案

是创建一个转发装饰器,检查每个方法调用流是否验证。对于 InputStream 这个装饰器可能看起来像这样:

  public final class CheckedInputStream扩展InputStream {
最终的InputStream委托;
布尔验证;
$ b $公共CheckedInputStream(InputStream流)抛出FileNotFoundException {
委托=流;
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();
返回读(b,0,b.length); (


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

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

$ b @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);

$ b @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())); 
//一些io,未显示
f_1.invalidate();

f_1.read(); //抛出IllegalStateException异常


This is a followup to anonymous file streams reusing descriptors

As per my previous question, I can't depend on code like this (happens to work in JDK8, for now):

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;

However, to prevent accidental errors and as a form of self-documentation, I would like to invalidate each file stream after I'm done using it - without closing the underlying file descriptor.

Each FileInputStream is meant to be independent, with positioning controlled by the RandomAccessFile. I share the same FileDescriptor to prevent any race conditions arising from opening the same path multiple times. When I'm done with one FileInputStream, I want to invalidate it so as to make it impossible to accidentally read from it while using the second FileInputStream (which would cause the second FileInputStream to skip data).

How can I do this?

notes:

  • the libraries I use require compatibiity with java.io.*
  • if you suggest a library (I prefer builtin java semantics if at all possible), it must be commonly available (packaged) for linux (the main target) and usable on windows (experimental target)
  • but, windows support isn't a absolutely required

Edit: in response to a comment, here is my workflow:

RandomAccessFile r = new RandomAccessFile(String path, "r");

int header_read;
int header_remaining = 4; // header length, initially

byte[]     ba = new byte[header_remaining];
ByteBuffer bb = new ByteBuffer.allocate(header_remaining);

while ((header_read = r.read(ba, 0, header_remaining) > 0) {
    header_remaining -= header_read;
    bb.put(ba, 0, header_read);
}

byte[] header = bb.array();

// process header, not shown
// the RandomAccessFile above reads only a small amount, so buffering isn't required

r.seek(0);

FileInputStream f_1 = new FileInputStream(r.getFD());

Library1Result result1 = library1.Main.entry_point(f_1)

// process result1, not shown
// Library1 reads the InputStream in large chunks, so buffering isn't required
// invalidate f_1 (this question)

r.seek(0)

int read;
while ((read = r.read(byte[4096] buffer)) > 0 && library1.continue()) {
    library2.process(buffer, read);
}

// the RandomAccessFile above is read in large chunks, so buffering isn't required
// in a previous edit the RandomAccessFile was used to create a FileInputStream. Obviously that's not required, so ignore

r.seek(0)

Reader r_1 = new BufferedReader(new InputStreamReader(new FileInputStream(r.getFD())));

Library3Result result3 = library3.Main.entry_point(r_2)

// process result3, not shown
// I'm not sure how Library3 uses the reader, so I'm providing buffering
// invalidate r_1 (this question) - bonus: frees the buffer

r.seek(0);

FileInputStream f_2 = new FileInputStream(r.getFD());

Library1Result result1 = library1.Main.entry_point(f_2)

// process result1 (reassigned), not shown
// Yes, I actually have to call 'library1.Main.entry_point' *again* - same comments apply as from before
// invalidate f_2 (this question)
//
// I've been told to be careful when opening multiple streams from the same
// descriptor if one is buffered. This is very vague. I assume because I only
// ever use any stream once and exclusively, this code is safe.
//

解决方案

A pure Java solution might be to create a forwarding decorator that checks on each method call whether the stream is validated or not. For InputStream this decorator may look like this:

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();
  }
}

You can use it like:

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

                   f_1.read(); // throws IllegalStateException

这篇关于在不关闭的情况下使流无效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆