我们的应用程序中存在一个问题,可以简化为此代码:
public static void main(String[] args) throws IOException, ClassNotFoundException {
File tempFile = File.createTempFile("teststream", "");
FileOutputStream fos = new FileOutputStream(tempFile);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeInt(1);
oos.writeObject("foo");
oos.writeInt(2);
oos.flush();
oos.close();
FileInputStream fis = new FileInputStream(tempFile);
ObjectInputStream ois = new ObjectInputStream(fis);
int n1 = ois.readInt();
Object o1 = ois.readObject();
int n2 = ois.readInt();
}
此代码有效,但如果您评论以下行:
Object o1 = ois.readObject();
以下一行
int n2 = ois.readInt();
将抛出EOFException
,尽管我的文件中有数据,因为我写了一个对象和一个整数。 javadoc of readInt不表示此行为。我有点担心这个EOFException
,因为我们希望在我们的代码中区分真正的,在文件异常和错误中没有其他内容可读内容类型一。
异常的堆栈跟踪是
Exception in thread "main" java.io.EOFException
at java.io.DataInputStream.readInt(DataInputStream.java:392)
at java.io.ObjectInputStream$BlockDataInputStream.readInt(ObjectInputStream.java:2793)
at java.io.ObjectInputStream.readInt(ObjectInputStream.java:968)
这意味着DataInputStream
中的以下代码会引发异常:
public final int readInt() throws IOException {
int ch1 = in.read();
int ch2 = in.read();
int ch3 = in.read();
int ch4 = in.read();
if ((ch1 | ch2 | ch3 | ch4) < 0)
throw new EOFException();
但是当输入流中有数据时,in.read()
不应该返回负数,所以我真的很感兴趣。
我的代码中是否可以执行某些操作来防止这种情况发生(知道我们可能会在某个时候调用readInd
使用writeObject
?
我正在使用这个版本的java:
java version "1.7.0_07"
OpenJDK Runtime Environment (IcedTea7 2.3.2) (ArchLinux build 7.u7_2.3.2-2-x86_64)
OpenJDK 64-Bit Server VM (build 23.2-b09, mixed mode)
答案 0 :(得分:4)
底层流用块头写入块。当您在写入对象时尝试readInt
时,找到了错误的块类型,并且in.read()
返回-1。
调用以下方法。
/**
* Attempts to read in the next block data header (if any). If
* canBlock is false and a full header cannot be read without possibly
* blocking, returns HEADER_BLOCKED, else if the next element in the
* stream is a block data header, returns the block data length
* specified by the header, else returns -1.
*/
private int readBlockHeader(boolean canBlock) throws IOException {
// code deleted
int tc = in.peek();
switch (tc) {
case TC_BLOCKDATA:
// code deleted
default:
if (tc >= 0 && (tc < TC_BASE || tc > TC_MAX)) {
throw new StreamCorruptedException(
String.format("invalid type code: %02X",
tc));
}
return -1;
}
-1表示当StreamCorruptedException
可能是更好的选择时已达到结束。
答案 1 :(得分:1)
如果您对该行Object o1 = ois.readObject();
发表评论,并且您执行了该程序,则n2
不会读取int
,而是会从序列化对象中读取4个字符。是的,您可以获得负值,具体取决于对象的序列化方式(例如,存储的对象的字节顺序,如果内存正确地存储,则以Big-Endian存储)。
答案 2 :(得分:1)
情况完全无效。如果您没有阅读您所写的内容,则行为未定义。它可能不应该在这种情况下抛出EOFException
,但是因为你不能指出一个说明当你做错事时它应该做什么的规范,你实际上没有一条腿站立起来