如何在两个输入流都停止工作的情况下读取相同的输入流两次

How to read same inputstream twice without both inputstreams stopping from working

我正在尝试创建一个可以通过套接字发送带有文本的日志的小型应用程序。当套接字被接受时,该套接字的输入流将像这样存储在 HashMap 中。

private HashMap<Integer,InputStream> allinputsstreams = new 
HashMap<Integer,InputStream>();

之后我将为当前输入流创建一个新的 JFrame

public LogListener(int socketid, SocketListener socketlistener, Gui gui) {
    this.socketid = socketid;
    this.gui = gui;
    this.inputstream = socketlistener.getClient(socketid);
    JFrame frame = new JFrame("Log listener");
    frame.setLocationRelativeTo(null);
    frame.setPreferredSize(new Dimension(framewidth,frameheight));
    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    logarea = new JTextArea();
    frame.add(logarea);
    frame.pack();
    frame.setVisible(true);
    frame.addWindowListener(this);
    listenthread = new Thread(this);
    listenthread.start();
}

然后我使用列表中的输入流接收数据并将其写入JFrame

public void run() {
    input = new DataInputStream(inputstream);
    while(!formclosed) {
        try {
            String addtext = input.readUTF();
            addtext = formatText(addtext);
            logarea.setText(logarea.getText() + addtext);
        } catch (EOFException e) {
            System.out.println("Looks like the client has been closed.");
            return;
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
    }
}

这适用于在 1 个 JFrame 上接收数据,但是一旦我打开 2 个 JFrame(意味着打开同一个输入流两次),输入流的 none 就不再工作了。我期待至少 1 个输入流仍然有效。

听起来您正试图在两个不同的视图中显示来自输入流的数据。你真的不能把一个简单的 InputStream 读两遍;相反,您需要某种缓冲。因此,与其尝试阅读它两次,我建议以两种方式之一修改您的代码,这两种方式都涉及对每个流仅使用一个读取循环:

  1. 修改您的读取循环以更新内部缓冲区而不是调用 logarea.setText(logarea.getText() + addtext);。每当读取循环更新缓冲区时,应该通知任何感兴趣的视图(通过您实现的某种观察者模式)内容已更改。

  2. 修改读取循环以更新所有感兴趣的视图,而不是为每个 JFrame 使用单独的读取循环。读取循环需要访问日志区域列表而不是单个 logarea。它将遍历列表并使用您现在用于 logarea.

  3. 的相同逻辑更新每个日志区域

关键是永远不要让两个读取循环访问同一个输入流。