Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java PipedInputStream available()方法返回值_Java_Inputstream_Pipe - Fatal编程技术网

Java PipedInputStream available()方法返回值

Java PipedInputStream available()方法返回值,java,inputstream,pipe,Java,Inputstream,Pipe,我正在尝试编写一段解锁代码,以便从数据库读取。在调用阻塞读取API之前,它基本上会检查是否有任何内容需要读取: int n = 0; if ((n = pipedInputStream_.available()) > 0) { pipedInputStream_.read(...) } 通过阅读,我无法确定该检查应该是什么,因为可能的值为零(表示没有数据,或关闭/中断流)或大于零。那么,打电话的人怎么知道有什么东西要读呢 返回可以不阻塞地从此输入流读取的字节数,如果此输入流已通

我正在尝试编写一段解锁代码,以便从数据库读取。在调用阻塞读取API之前,它基本上会检查是否有任何内容需要读取:

int n = 0;
if ((n = pipedInputStream_.available()) > 0) {
     pipedInputStream_.read(...)
}
通过阅读,我无法确定该检查应该是什么,因为可能的值为零(表示没有数据,或关闭/中断流)或大于零。那么,打电话的人怎么知道有什么东西要读呢

返回可以不阻塞地从此输入流读取的字节数,如果此输入流已通过调用其close()方法关闭,或者管道未连接或已断开,则返回0

从源代码看,似乎只有值为零或大于零

public synchronized int available() throws IOException {
    if(in < 0)
        return 0;
    else if(in == out)
        return buffer.length;
    else if (in > out)
        return in - out;
    else
        return in + buffer.length - out;
}
public synchronized int available()引发IOException{
if(in<0)
返回0;
else if(in==out)
返回缓冲区长度;
否则如果(输入>输出)
返回输入输出;
其他的
返回in+buffer.length-out;
}
如果
available()
返回零,则当前没有可读取的字节。根据您所引用的文档,这可能是因为以下几个原因:

  • 管道是封闭的
  • 管子断了
  • 所有以前可用的输入(如果有)都已使用
available()
中的零返回值可能意味着发生了错误,这意味着您将来将无法通过管道读取更多数据,但在这里无法确定,因为零可能表示上面的第三种情况,即在
InputStream#read()上阻塞
最终可能会产生更多的数据,相应的
OutputStream
端将通过管道推送这些数据

在有更多数据可用之前,我不认为可以使用
available()
轮询
PipedInputStream
,因为您永远无法区分上面的终端情况(第一个和第二个)和读卡器比写卡器更饿。像许多流接口一样,在这里您也必须尝试使用并准备失败。这就是陷阱
InputStream#read()
将被阻止,但直到您在尝试读取时承诺阻止,您才能发现不再有输入


将消费行为建立在
available()
上是不可行的。如果它返回一个正数,则有一些内容需要阅读,但当然,即使是现在可用的内容也可能“不足以”满足您的消费者。如果您以阻塞方式提交一个线程来使用
InputStream
,并使用
available()
跳过轮询,那么您的应用程序将更易于管理。让
InputStream#read()
成为您在这里的唯一oracle。

我需要一个过滤器来拦截慢速连接,我需要尽快关闭DB连接,所以我最初使用Java管道,但仔细看它们的实现时,它都是同步的,所以我最终创建了我自己的QueueInputStream,使用一个小缓冲区和阻塞队列将缓冲区放入队列。一旦缓冲区满了,它是无锁的,除了LinkedBlockingQueue使用的锁条件,在小缓冲区的帮助下,它应该是便宜的,此类仅用于每个实例的单个生产者和消费者:

import java.io.IOException;
import java.io.OutputStream;
import java.util.concurrent.*;

public class QueueOutputStream extends OutputStream
{
  private static final int DEFAULT_BUFFER_SIZE=1024;
  private static final byte[] END_SIGNAL=new byte[]{-1};

  private final BlockingQueue<byte[]> queue=new LinkedBlockingDeque<>();
  private final byte[] buffer;

  private boolean closed=false;
  private int count=0;

  public QueueOutputStream()
  {
    this(DEFAULT_BUFFER_SIZE);
  }

  public QueueOutputStream(final int bufferSize)
  {
    if(bufferSize<=0){
      throw new IllegalArgumentException("Buffer size <= 0");
    }
    this.buffer=new byte[bufferSize];
  }

  private synchronized void flushBuffer()
  {
    if(count>0){
      final byte[] copy=new byte[count];
      System.arraycopy(buffer,0,copy,0,count);
      queue.offer(copy);
      count=0;
    }
  }

  @Override
  public synchronized void write(final int b) throws IOException
  {
    if(closed){
      throw new IllegalStateException("Stream is closed");
    }
    if(count>=buffer.length){
      flushBuffer();
    }
    buffer[count++]=(byte)b;
  }

  @Override
  public synchronized void close() throws IOException
  {
    flushBuffer();
    queue.offer(END_SIGNAL);
    closed=true;
  }

  public Future<Void> asyncSendToOutputStream(final ExecutorService executor, final OutputStream outputStream)
  {
    return executor.submit(
            new Callable<Void>()
            {
              @Override
              public Void call() throws Exception
              {
                try{
                  byte[] buffer=queue.take();
                  while(buffer!=END_SIGNAL){
                    outputStream.write(buffer);
                    buffer=queue.take();
                  }
                  outputStream.flush();
                } catch(Exception e){
                  close();
                  throw e;
                } finally{
                  outputStream.close();
                }
                return null;
              }
            }
    );
  }

}
import java.io.IOException;
导入java.io.OutputStream;
导入java.util.concurrent.*;
公共类QueueOutputStream扩展了OutputStream
{
私有静态final int DEFAULT_BUFFER_SIZE=1024;
私有静态最终字节[]END_信号=新字节[]{-1};
private final BlockingQueue=新建LinkedBlockingDeque();
专用最终字节[]缓冲区;
私有布尔闭合=假;
私有整数计数=0;
公共队列输出流()
{
该值(默认缓冲区大小);
}
公共QueueOutputStream(最终int-bufferSize)
{
if(bufferSize0){
最终字节[]复制=新字节[计数];
System.arraycopy(缓冲区,0,拷贝,0,计数);
报价单(复印件);
计数=0;
}
}
@凌驾
公共同步的无效写入(最终int b)引发IOException
{
如果(关闭){
抛出新的IllegalStateException(“流已关闭”);
}
如果(计数>=缓冲区长度){
flushBuffer();
}
缓冲区[计数++]=(字节)b;
}
@凌驾
public synchronized void close()引发IOException
{
flushBuffer();
排队报盘(结束信号);
关闭=真;
}
公共未来asyncSendToOutputStream(最终执行器服务执行器,最终输出流OutputStream)
{
返回执行者。提交(
新的可调用()
{
@凌驾
public Void call()引发异常
{
试一试{
byte[]buffer=queue.take();
while(缓冲区!=结束信号){
outputStream.write(缓冲区);
buffer=queue.take();
}
outputStream.flush();
}捕获(例外e){
close();
投掷e;
}最后{
outputStream.close();
}
返回null;
}
}
);
}
}

0并不意味着流已关闭或中断。根据规范,零或大于零是唯一允许的结果。您能否澄清为什么说零并不意味着关闭或断流?请看seh的解释,我同意。Java文档还说:“返回:可以从该输入流中读取而不阻塞的字节数,或者如果该输入流已通过调用其close()方法关闭,或者如果管道未连接或已断开,则返回0。”您误解了。零表示在没有阻塞的情况下没有要读取的数据,或者流已关闭,或者管道未连接,或者管道已断开。这不仅仅意味着其中一种情况,当然。附件消除了第一个sta引起的混乱