【问题标题】:How to read same inputstream twice without both inputstreams stopping from working如何在两个输入流都停止工作的情况下两次读取相同的输入流
【发布时间】:2017-09-12 05:29:39
【问题描述】:

我正在尝试创建一个可以通过套接字发送带有文本的日志的小型应用程序。当套接字被接受时,该套接字的输入流将像这样存储在 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(意味着打开相同的输入流两次),那么所有输入流都不再工作了。我期待至少 1 个输入流仍然可以工作。

【问题讨论】:

  • “输入流都不起作用”是什么意思?你有例外吗?僵局?还有什么?
  • 我没有得到任何异常,但是当我打开 1 时它会发送数据并将其写入 JFrame(这就是我想要的)但是当我打开另一个时(打开输入流两次)然后没有输入流发送我需要的数据
  • 输入流不是绑定到单独的套接字上吗?为什么要读取相同的输入流两次?
  • 是的,但是输入流被放在一个 HashMap 中,其中一个数字作为键,输入流作为值。当我从该 HashMap 打开例如数字 1 时,它会使用该流。之后我打开数字 2 然后它们都工作,因为它们是不同的输入流。但是当我打开 1 号并再次打开 1 号之后,它们都停止工作了。
  • 你不能。输入流是流,流的含义是它流过你,一次。如果你想重新阅读它,你必须重新创建它,重新打开文件,重新连接到源(如果你可以的话)等等。

标签: java sockets inputstream datainputstream


【解决方案1】:

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

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

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

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

【讨论】:

  • 我想我现在有点明白了,我会更改我的代码,谢谢你的回答。
  • 太棒了!它对我有用。我正在将流数据写入 ByteArrayOutputStream 的对象并立即关闭输入流和套接字。然后,当我需要数据时,我可以从 ByteArrayOutputStream 的对象中使用它。纠正我,如果我做错了什么。
  • @KishoreKumarKorada - 听起来对我来说是正确的方法。
猜你喜欢
  • 2012-03-19
  • 2019-07-15
  • 2021-04-19
  • 2014-07-12
  • 1970-01-01
  • 1970-01-01
  • 2021-06-04
  • 1970-01-01
相关资源
最近更新 更多