4

我在客户端有这段代码:

DataInputStream dis = new DataInputStream(socketChannel.socket().getInputStream());
while(dis.available()){
     SomeOtherClass.method(dis);
}

available()不断返回0,尽管流中有可读数据。所以在要读取的实际数据完成后,将空数据传递给要读取的其他类,这会导致损坏。

经过一番搜索;我发现available()与套接字一起使用时不可靠,我应该从流中读取前几个字节以实际查看数据是否可用于解析。

但就我而言;我必须将从套接字获得的引用传递DataInputStream给我无法更改的其他类。

是否可以在不破坏它的情况下读取几个字节DataInputStream或任何其他建议?

4

3 回答 3

5

在两者之间放置一个PushbackInputStream可以让您在不破坏数据的情况下读取一些字节。

编辑:下面未经测试的代码示例。这是来自记忆。

static class MyWrapper extends PushbackInputStream {
    MyWrapper(InputStream in) {
        super(in);
    }

    @Override
    public int available() throws IOException {
        int b = super.read();
        // do something specific?
        super.unread(b);
        return super.available();
    }
}

public static void main(String... args) {
    InputStream originalSocketStream = null;
    DataInputStream dis = new DataInputStream(new MyWrapper(originalSocketStream));
}
于 2012-08-16T07:52:36.887 回答
2

这应该有效:

PushbackInputStream pbi = new PushbackInputStream(socketChannel.socket().getInputStream(), 1);
int singleByte;
DataInputStream dis = new DataInputStream(pbi);
while((singleByte = pbi.read()) != -1) {
    pbi.unread(singleByte);
    SomeOtherClass.method(dis);
}

但请注意,此代码的行为与可用的示例不同(如果可用的话),因为可用不会阻塞,但读取可能会阻塞。

于 2012-08-16T08:13:53.097 回答
1

但是available()一直返回0,虽然流中有可读数据

如果available()返回零,则:

  1. 您正在使用的输入流不支持available(),因此它只返回零。这里不是这种情况,因为您使用的是DataInputStream直接包装在套接字输入流周围的,并且该配置确实支持available(), OR ...

  2. 流中没有可读数据。这里似乎就是这种情况。实际上,您无需实际读取即可知道流中有可读数据的唯一可能方法是调用available()并获得肯定的结果。没有其他的说法。

的正确用法很少availabe(),这不是其中之一。为什么仅仅因为套接字接收缓冲区中没有任何数据就退出该循环?您应该摆脱该循环的唯一方法是获得流结束条件。

我应该从流中读取前几个字节以实际查看数据是否可用于解析。

这甚至没有意义。如果您可以从流中读取任何内容,则有可用的数据,如果不能,则没有。

只需阅读、阻止各种表现形式的 EOS 并对其做出正确反应。

于 2012-08-16T10:22:17.837 回答