Java ObjectInputStream使用更大的对象抛出EOFException

时间:2017-05-21 17:58:18

标签: java android deserialization objectinputstream eofexception

我有这种方法来反序列化:

public static Object deserialize(byte[] data) throws IOException, ClassNotFoundException {
    ByteArrayInputStream in = new ByteArrayInputStream(data);
    ObjectInputStream is = new ObjectInputStream(in);
    Object res = is.readObject();
    is.close();
    in.close();
    return res;
}

和这个序列化:

public static byte[] serialize(Object obj) throws IOException {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    ObjectOutputStream os = new ObjectOutputStream(out);
    os.writeObject(obj);
    byte[] res = out.toByteArray();
    out.close();
    os.close();
    return res;
}

我使用这些方法来序列化和反序列化一个类对象,它只有一个字符串和另一个类的arrayList,在两个设备之间交换。对象的类和arrayList的类都实现了serializable。

当我在arrayList中发送一个最多包含3个元素的对象时,这些方法可以很好地工作。但是,当arrayList具有4个或更多元素时,接收对象的设备仍会检测到某些数据已“到达”但是deserialize方法在“Object res = is.readObject();”中生成“EOFException”。线。

关于问题可能是什么的任何想法?

修改

这是arrayList的类:

import java.io.Serializable;

public class Info implements Serializable {

    public Info() {
        ...
    }

    ...
}

这是对象的类:

import java.io.Serializable;
import java.util.ArrayList;

public class BluetoothDataContainer implements Serializable{

    private ArrayList<Info> dataList;
    private String originDevice;

    public BluetoothDataContainer(String originDevice){
        dataList= new ArrayList<Info>();
        this.originDevice = originDevice;
    }

    ...
}

这是我用来发送对象的代码:

BluetoothDataContainer data = new BluetoothDataContainer(mBluetoothAdapter.getName());

...

// add needed info to variable 'data'

...

s.write(data);

's'是一个带有'write'方法的线程:

private BluetoothSocket mmSocket = bluetoothDevice.createRfcommSocketToServiceRecord(ID_CONNECTION);
private OutputStream mmOutStream = mmSocket.getOutputStream();

...

public void write(BluetoothDataContainer m) {
    try {
        mmOutStream.write(serialize(m));
    } catch (IOException e) {
        this.mContext.showToast("IOException caught in thread ConnectedThread [Bluetooth connection handler] - write() !");
    }
    //cancel();
    this.interrupt();
}

这就是我在阅读时处理对象的方式:

private final Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case 1:
                byte[] readBuf = (byte[]) msg.obj;
                // construct a string from the valid bytes in the buffer
                final BluetoothDataContainer data;
                try {
                    data = (BluetoothDataContainer) deserialize(readBuf);

                    ...

                } catch (IOException | ClassNotFoundException e) {
                    e.printStackTrace();
                }
                break;
            default:
                break;
        }
    }
};

这就是我阅读对象的方式:

private final Handler mHandler;   // value set in the constructor

...

public void run() {

    mmInStream = bluetoothSocket.getInputStream();

    byte[] buffer = new byte[1024];  // buffer store for the stream
    int bytes;

    try {
        // Read from the InputStream
        bytes = mmInStream.read(buffer);
        this.mContext.showToast("ConnectedThread [Bluetooth connection handler] data received !");

        // Send the obtained bytes to the UI activity
        mHandler.obtainMessage(1, bytes, -1, buffer).sendToTarget();

    } catch (IOException e) {
        this.mContext.showToast("IOException caught in thread ConnectedThread [Bluetooth connection handler] - run() !");
    }

}

1 个答案:

答案 0 :(得分:0)

很明显,你还没有交换过&#39;在失败的情况下整个字节数组。

bytes = mmInStream.read(buffer);

你不可能仅凭这一点了解你是否已阅读:

  • 整个消息
  • 少于一条消息
  • 不止一条消息。

因为你已经有一个带输入和输出流的套接字,所以它打败了我为什么要创建字节数组。只需将ObjectOutputStream包裹在套接字输出流周围,然后使用writeObject()。在接收器处,将ObjectInputStream包裹在套接字输入流周围并使用readObject()

请注意,您应该在套接字的生命周期中使用相同的对象流,如果要以两种方式发送对象,则必须在同一套接字的对象输入流之前创建对象输出流:否则可能会出现死锁。