Java ObjectInputStream 使用更大的对象抛出 EOFException
Java ObjectInputStream throws EOFException with bigger object
我有反序列化的方法:
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;
}
我使用这些方法序列化和反序列化一个 class 对象,它只有一个字符串和另一个 class 的数组列表,在两个设备之间交换。对象的class和arrayList的class都实现了serializable.
当我在 arrayList 中发送最多包含 3 个元素的对象时,这些方法非常有效。然而,当arrayList有4个或更多元素时,接收对象的设备仍然检测到一些数据已经“到达”但是反序列化方法在“Object res = is.readObject();”中产生了一个“EOFException”。行。
关于问题可能是什么的任何想法?
编辑
这是 arrayList 的 class:
import java.io.Serializable;
public class Info implements Serializable {
public Info() {
...
}
...
}
这是对象的class:
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() !");
}
}
很明显,在失败的情况下,您没有 'exchanged' 整个字节数组。
bytes = mmInStream.read(buffer);
仅凭此您不可能知道您是否阅读过:
- 整封邮件
- 少于一条消息
- 不止一条消息。
因为您已经有一个带有输入和输出流的套接字,所以我完全不明白为什么要创建字节数组。只需将 ObjectOutputStream
包裹在套接字输出流周围并使用 writeObject()
。在接收方,将 ObjectInputStream
包裹在套接字输入流周围并使用 readObject()
.
注意你应该在套接字的生命周期中使用相同的对象流,如果你以两种方式发送对象,你必须在对象输入流之前为同一个套接字创建对象输出流:否则你会得到一个死锁。
我有反序列化的方法:
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;
}
我使用这些方法序列化和反序列化一个 class 对象,它只有一个字符串和另一个 class 的数组列表,在两个设备之间交换。对象的class和arrayList的class都实现了serializable.
当我在 arrayList 中发送最多包含 3 个元素的对象时,这些方法非常有效。然而,当arrayList有4个或更多元素时,接收对象的设备仍然检测到一些数据已经“到达”但是反序列化方法在“Object res = is.readObject();”中产生了一个“EOFException”。行。
关于问题可能是什么的任何想法?
编辑
这是 arrayList 的 class:
import java.io.Serializable;
public class Info implements Serializable {
public Info() {
...
}
...
}
这是对象的class:
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() !");
}
}
很明显,在失败的情况下,您没有 'exchanged' 整个字节数组。
bytes = mmInStream.read(buffer);
仅凭此您不可能知道您是否阅读过:
- 整封邮件
- 少于一条消息
- 不止一条消息。
因为您已经有一个带有输入和输出流的套接字,所以我完全不明白为什么要创建字节数组。只需将 ObjectOutputStream
包裹在套接字输出流周围并使用 writeObject()
。在接收方,将 ObjectInputStream
包裹在套接字输入流周围并使用 readObject()
.
注意你应该在套接字的生命周期中使用相同的对象流,如果你以两种方式发送对象,你必须在对象输入流之前为同一个套接字创建对象输出流:否则你会得到一个死锁。