【问题标题】:ObjectInputStream.read() returning -1, but readObject returns the object [closed]ObjectInputStream.read()返回-1,但readObject返回对象[关闭]
【发布时间】:2013-02-18 07:48:45
【问题描述】:

我要序列化一个对象并反序列化该对象,但我得到:

  1. 0 表示可用()
  2. -1 for read()
  3. readByte() 的 EOFException

    public static Element getCacheObject(String key, String cacheName, String server) throws IOException, ClassNotFoundException, ConnectException {
        String url = StringUtils.join(new String[] { server, cacheName, key}, "/");
        GetMethod getMethod = new GetMethod(url);
        ObjectInputStream oin = null;
        InputStream in = null;
        int status = -1;
        Element element = null;
        try {
            status = httpClient.executeMethod(getMethod);
            if (status == HttpStatus.SC_NOT_FOUND) { // if the content is deleted already               
                return null;
            }
            in = getMethod.getResponseBodyAsStream();
            oin = new ObjectInputStream(in);
            System.out.println("oin.available():" + oin.available()); // returns 0
            System.out.println("oin.read():" + oin.read()); // returns -1
            element = (Element) oin.readObject(); // returns the object
        }
        catch (Exception except) {
            except.printStackTrace();
            throw except;
        }
        finally {
            try {
                oin.close();
                in.close();
            }
            catch (Exception except) {
                except.printStackTrace();
            }
        }
    
        return element;
    }
    

我在这里错过了什么?

【问题讨论】:

  • 使用read() 和其他方法(包括readFully())的目的是能够在readObject() 抛出InvalidClassException 的情况下重建对象。但是,似乎只有readObject() 上的ObjectInputStream 给出了预期的结果。

标签: java serialization deserialization ehcache objectinputstream


【解决方案1】:

我认为您会看到这种行为,因为您首先从InputStream 创建ObjectInputStream,然后才在InputStream 上检查available。如果您检查ObjectInputStream 的构造函数,您可以看到以下内容:

public ObjectInputStream(InputStream in) throws IOException {
    verifySubclass();
    bin = new BlockDataInputStream(in);
    handles = new HandleTable(10);
    vlist = new ValidationList();
    enableOverride = false;
    readStreamHeader();
    bin.setBlockDataMode(true);
} 

有一个方法readStreamHeader 从输入流中读取标头。所以有可能在ObjectInputStream的构造过程中,所有的数据都是从InputStream读取的。

【讨论】:

  • 我也在ObjectInputStream而不是InputStream上测试了available()read(),但结果是一样的。
  • @JMOkomba 你应该在创建ObjectINputStream 之前测试availableread 因为我认为ObjectInputStream 的构造函数会读取所有数据。
  • @JMOkomba 还请记住,调用 read 可能会破坏流,因为 ObjectInputStream 不会获取此字节并且无法解析对象。
  • 你是对的。如果我在创建 ObjectInputStream 之前调用 available()read() 它会给出结果
【解决方案2】:

您在in 变量上调用available and read,但在oin 变量上调用readObject

【讨论】:

  • 我已将 available()read() 更改为调用 oin 而不是 in。但是,结果是一样的。
【解决方案3】:

你在 EOS 上告诉你的信息流。有零个字节available() 无需阻塞即可读取; read() 返回 -1 表示 EOS; readLine() 将返回 null; readXXX() 也会为任何其他指示 EOS 的 XXX 抛出 EOFException;并且readObject() 返回一个Object,因为您正在读取缓冲的ObjectInputStream,而不是您调用所有其他方法的流。注意你不应该打电话read() 只是为了测试EOS;并且available() 首先不是对 EOS 的有效测试:请参阅 Javadoc。

【讨论】:

  • 为什么available 不是 EOS 的有效测试?那什么是有效的呢?根据 javadoc available 应该返回 0 如果它到达流的末尾。
  • @NikitaBeloglazov 因为它只告诉你可以读取多少字节没有阻塞。因此返回值为零至少有两个含义。检测 EOS 的唯一方法是尝试读取。
  • 我明白你的意思。但是用于 Returns 的 javadoc 说明如下:an estimate of the number of bytes that can be read (or skipped over) from this input stream without blocking or 0 when it reaches the end of the input stream.。所以它很容易返回 0 当它到达结束时。我认为这很令人困惑。
  • 啊,好的。我明白了。我以前读它就像“只有当它到达结束时才为0”。现在我明白这意味着更多“当它到达结束时它返回 0”,而不是“仅”。
  • @NikitaBeloglazov 它实际上可能意味着三件事,如果不是更多的话。 1:没有任何内容可以在没有阻塞的情况下读取(但在这一点和流结束之间可能有 TB); 2:流结束; 3:InputStream 的这个实现没有实现available()(例如,从SSLSocket 获得的输入流)。
猜你喜欢
  • 2020-11-04
  • 2020-02-17
  • 1970-01-01
  • 1970-01-01
  • 2013-01-08
  • 2023-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多