Java 我应该在何时何地使用close()方法来避免ObjectInputStream中的IOException?

Java 我应该在何时何地使用close()方法来避免ObjectInputStream中的IOException?,java,sockets,networking,tcp,objectinputstream,Java,Sockets,Networking,Tcp,Objectinputstream,我正在尝试通过tcp从客户端程序读取对象。正如您在这一行中看到的,我创建了objectInput: ObjectInputStream objectInput = new ObjectInputStream(incoming.getInputStream()); 然后从另一个程序读取我的输入。在我做了一些小改动来清理程序之前,它一直工作得很好。我个人认为我补充说 objectInput.clsoe(); 我的问题是,在阅读对象之后,我应该关闭objectInputStream还是保持不关闭?

我正在尝试通过tcp从客户端程序读取对象。正如您在这一行中看到的,我创建了objectInput:

ObjectInputStream objectInput = new ObjectInputStream(incoming.getInputStream());
然后从另一个程序读取我的输入。在我做了一些小改动来清理程序之前,它一直工作得很好。我个人认为我补充说

objectInput.clsoe();
我的问题是,在阅读对象之后,我应该关闭objectInputStream还是保持不关闭?我应该在使用后立即关闭它,还是在if块末尾或程序末尾关闭它?收盘的影响是什么?顺便说一下,我已经阅读了关闭文档

以下是错误:

java.io.EOFException
    at java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2280)
    at java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:2749)
    at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:779)
    at java.io.ObjectInputStream.<init>(ObjectInputStream.java:279)
    at Server.ClientWorker.run(MyCollectionServer.java:116)
    at java.lang.Thread.run(Thread.java:680)
这是我的密码:

    public static void main(String[] args) {
        ServerSocket serverSocket = null;
        try 
        {
            serverSocket = new ServerSocket(port);  
        } 
        catch (IOException e) 
                {
            e.printStackTrace();
        }
        while(true)
        {   
            ClientWorker w;
            try
            {   
                w = new ClientWorker(serverSocket.accept());
                Thread t = new Thread(w);
                t.start();
            }
            catch(IOException e)
            {
                e.printStackTrace();
                break;
            }   
        }
    }
}

class ClientWorker implements Runnable
{
.....
    private Socket incoming;
    public ClientWorker(Socket incoming)
    {
        myList = new ArrayList<PureAlbum>();
        loadList();
        this.incoming = incoming;
    }

.....
    public synchronized  void run()
    {

else if(request.compareTo("AddAlbum")==0)
        {
            try
            {
                ObjectInputStream objectInput = new ObjectInputStream(incoming.getInputStream()); //This is the line mentioned in the error
                PureAlbum object = (PureAlbum) objectInput.readObject();


                if(object instanceof CDAlbum)
                {
                    CDAlbum a = (CDAlbum) object;
                    myList.add(a);
                    System.out.println("Artist = " + a.getArtist());
                }
                else if(object instanceof Client.au.edu.uow.Collection.DVDAlbum)
                {
                    myList.add((DVDAlbum) object);              
                }
                else
                {
                    System.err.println("Warning : The object to add to database is unknown! "+ object.getClass() + "*");
                    System.exit(0);
                }


            }
            catch (UnknownHostException e) 
            {
                System.err.println("Can not read the host name");
                e.printStackTrace();
            } 
            catch (IOException e) 
            {
                System.err.println("Can not read the FILE name"); //This exception has been called
                e.printStackTrace(); 
            }
            catch (ClassNotFoundException e) 
            {
                e.printStackTrace();
            }
        }

你应该在完成阅读或写作后关闭流。 在本例中,当您完全读取了文件并且不再需要从流中读取文件时,应该关闭InputStream

简而言之,您应该在流的工作结束时关闭它。 它可能在程序的末尾或if循环之后…取决于您的用例


希望这会有所帮助。

您的代码片段相当长,因此我将尝试给您一个一般性的答案,希望它能帮助您

java 7之前stream.close的典型使用模式为:

InputStream in = null; 
try {
    InputStream in = .....; // create your input stream;
    // use input stream
} catch (IOException e) {
    // do what you need here
} finally {
    if (in != null) {
        in.close();
    }
}
或者简单地将该方法声明为抛出IOException,然后写入:

InputStream in = null; 
try {
    InputStream in = .....; // create your input stream;
    // use input stream
} finally {
    if (in != null) {
        in.close();
    }
}
请注意,此示例不包含catch部分

从java 7开始,我们可以享受该语言的新功能:

try (
    InputStream in = .....; // create your input stream;
) {
    // use input stream
}

你甚至不必打电话给close。定义到try块头中的所有实现接口可关闭的资源都将自动关闭。

这一行堆栈跟踪表明,在初始化ObjectInputStream时,而不是在关闭时发生异常

at java.io.ObjectInputStream.<init>(ObjectInputStream.java:279)

最可能的原因是远程客户端没有打开ObjectOutputStream。它可能已经写入了其他类型的数据,或者它可能已经关闭了其输出流或者只是退出了。

我是这样做的,不同的示例:

private void readFile() throws Exception {
    FileInputStream fis = null;
    ObjectInputStream ois = null;
    Object aux = null;

    try {

        fis = new FileInputStream("lib.dat");
        ois = new ObjectInputStream(fis);

        do {
            aux = ois.readObject();
            if (aux instanceof MyObject)
                this.myObjectInstance.add((MyObject) aux);
        } while (true);

    } catch (EOFException e) {
        ois.close();
    }
}
通过这种方式,我将向楼上发送任何相关的错误异常以进行处理,一旦启动EndOfFileException,就会专门捕获该异常以正确关闭流

必须在Try块外部定义对象,才能从Catch块访问该对象


close方法也可以抛出一个IOException,而我们的Try块无法捕获它,它必须通过readFile方法的通用抛出异常来传递。

如果在Java 7上,请使用自动资源管理。如果没有,请使用finally块关闭。谢谢您的回复。在我看来,这个错误并不是因为亲密。因为当它到达ObjectInputStream objectInput=new ObjectInputStreamincoming.getInputStream时;它获取错误。关闭。我认为他正在为每条消息打开一个新的ObjectInputStream,并且没有找到正确的流头,等等,因为对等方没有打开一个新的对应ObjectOutputStream。在连接游戏的生命周期中使用相同的流是旧的。问题是我向服务器发送了一条消息add,然后向服务器中的数据库发送了要添加的对象。在对象端,我首先读了add消息,这很酷,但是我读了还没有发送的对象,为了避免这个问题,我添加了Thread.sleep1000;发送消息后添加到客户端。无论如何,感谢您的支持reply@Bernard将睡眠添加到网络代码中只是一个简单的编程。可能需要刷新输出流。