【问题标题】:ObjectInputStream doesn't have available bytes after being constructed with a ByteArrayInputStreamObjectInputStream 在使用 ByteArrayInputStream 构造后没有可用字节
【发布时间】:2025-12-05 05:05:01
【问题描述】:

我正在构建一个处理二进制反序列化的类。方法open() 接收InputStreamOutputStream。这些是由另一个接收路径作为参数的open() 方法创建的。 InputStream 实际上是 ByteArrayInputStream。 我已经做了一些测试来证明InputStream 到达open() 方法的内容——实际上是这样。但是当我尝试使用它设置ObjectInputStream 时,它不起作用。没有抛出异常,但是当我尝试从中读取字节时,它总是给我-1

BinaryStrategy 类

public class BinaryStrategy implements SerializableStrategy{
  public BinaryStrategy(){
    try{
        open("products.ser");
    }catch(IOException ioe){

    }
  } 
  @Override
  public void open(InputStream input, OutputStream output) throws IOException  {
    try{
        this.ois = new ObjectInputStream(input);
    }catch(Exception ioe){
        System.out.println(ioe);
    }
    this.oos = new ObjectOutputStream(output);
  }
  @Override
  public void writeObject(fpt.com.Product obj) throws IOException {
    oos.writeObject(obj);
    oos.flush();
  }
  @Override
  public Product readObject() throws IOException {
    Product read = new Product();
    try{
        read.readExternal(ois);
    }catch(IOException | ClassNotFoundException exc){
        System.out.println(exc);
    }
    return read;
  }
}

接口SerializableStrategy(只是默认方法)

    default void open(Path path) throws IOException {
    if (path != null) {
        ByteArrayInputStream in = null;
        if (Files.exists(path)) {
            byte[] data = Files.readAllBytes(path);
            in = new ByteArrayInputStream(data);
        }
        OutputStream out = Files.newOutputStream(path);
        open(in, out);
    }

产品类别

public class Product implements java.io.Externalizable {
    @Override
public void writeExternal(ObjectOutput out) throws IOException {
    out.writeLong(getId());
    out.writeObject(getName());
    out.writeObject(getPrice());
    out.writeObject(getQuantity());
}

@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
    this.setId((Long)in.readLong());
    this.setName((String) in.readObject());
    this.setPrice((Double) in.readObject());
    this.setQuantity((Integer) in.readObject());
}

我不得不个性化它,因为属性是SimplePropertys

public void open(InputStream input, OutputStream output)我尝试做一些如下测试:

    public void open(InputStream input, OutputStream output) throws IOException {
    try{
        System.out.println(input.available() + " " + input.read() + " " + input.read());
        //is gives me: 181 172 237
        //181 is the exact size of the file I have, so i think that the Output is ok
        //172 237 - just some chars that are in the file
        //I know that for now on it is going to give me an excepetion because
        // of the position of the index that is reading. I did it just to test
        this.ois = new ObjectInputStream(input);
    }catch(Exception ioe){
        System.out.println(ioe);
    }
    this.oos = new ObjectOutputStream(output);
}

然后是另一个测试:

public void open(InputStream input, OutputStream output) throws IOException {
    try{
        this.ois = new ObjectInputStream(input);
        System.out.println(ois.available() + " " + ois.read());
        //here is where I am receiving -1 and 0 available bytes!
        //so something is going wrong right here.
        //i tried to just go on and try to read the object,
        //but I got a EOFException, in other words, -1.
    }catch(Exception ioe){
        System.out.println(ioe);
    }
    this.oos = new ObjectOutputStream(output);
}

【问题讨论】:

  • 把剩下的代码给我们看看,只有这个我们无能为力
  • 请告诉我们你得到-1的代码
  • 好了,刚刚编辑好了

标签: java serialization inputstream objectinputstream bytearrayinputstream


【解决方案1】:

请检查path所代表的文件是否有写入java对象。
来自 ObjectInputStream API 文档https://docs.oracle.com/javase/7/docs/api/java/io/ObjectInputStream.html

ObjectInputStream 反序列化原始数据和之前使用 ObjectOutputStream 编写的对象。

ObjectInputStream 用于恢复之前序列化的那些对象。

如果您正在执行this.ois.readObject(),而您得到的是-1,则文件中可能不包含对象。

更新:readObject 返回一个对象,而不是 int。如果您使用ois 中的read 方法,并且得到-1,则该文件为空。

此外,您的文件可能包含 -1 作为其内容 ;)

【讨论】:

  • 感谢您的回答!但是我使用ObjectOutputStream 来编写我要反序列化的文件,因此该文件必须包含一个序列化对象。正如我所说,OutputStream,实际上是一个ByteArrayOutputStream,它携带着一些东西。我使用available()read() 方法来证明这一点并且它确实有效。
  • 我看到您正在从path 读取对象并在同一path 上打开newOutputStream。请注意,这将清除文件。检查您在写入文件时是否遇到任何异常。
【解决方案2】:

ObjectInputStream,内部使用BlockDataInputStream 执行其读取操作。当您调用read 时,这会读取一个数据块,而不仅仅是我们预期的一个字节。只有当它作为“块”落下时才会读取一个字节

输出也不是我所期望的。 但是,如果您查看ObjectInputStream.read() 的代码,就会发现它是有道理的。

因此,在您的情况下,仅使用 readObject 来恢复对象的状态是有意义的。

又是你的代码...

class SimpleJava {

    public static void open(InputStream input, OutputStream output) throws IOException {

        try {
            ObjectInputStream ois = new ObjectInputStream(input);
            System.out.println(ois.available());// 0
            System.out.println(ois.available() + " " + ois.read() + " " + ois.read());// 0 -1 -1
            // Reads the object even if the available returned 0 
            // and ois.read() returned -1
            System.out.println("object:" + ois.readObject());// object:abcd
        }
        catch (Exception ioe) {
            ioe.printStackTrace();
        }
    }

    static void open(Path path) throws IOException {

        if (path != null) {
            ByteArrayInputStream in = null;
            if (Files.exists(path)) {
                byte[] data = Files.readAllBytes(path);
                in = new ByteArrayInputStream(data);
            }
            OutputStream out = Files.newOutputStream(path);
            open(in, out);
        }
    }

    public static void main(String[] args) throws Exception {

        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("/home/pradhan/temp.object")));
        oos.writeObject("abcd");//writes a string object for us to read later
        oos.close();
        //
        open(FileSystems.getDefault().getPath("/home/user/temp.object"));
    }
}

这是输出...

0
0 -1 -1
object:abcd

【讨论】:

    【解决方案3】:

    问题是我读错了ObjectInputStream。就像:

    read.readExternal(ois);
    

    但正确的做法是:

    read = (Product)ois.readObject();
    

    由于我这样做时遇到的异常,我认为问题在于使用 ByteArrayInputStreamObjectInputStream 的构造。 多么大的错误! :D

    感谢所有试图提供帮助的人。

    【讨论】: