printwriter忽略除最后一行以外的已发送行

xvw2m8pv  于 2021-07-13  发布在  Java
关注(0)|答案(2)|浏览(288)

我编写了一个javaswing程序,它在串行端口侦听(我使用jserialcomm库)。程序应该在控制台(已经工作)、文本区域字段(也工作)和文件(不工作)中显示接收到的数据。
接收过程从按下一个按钮开始,到按下另一个按钮结束。
我使用swingworker类将gui更改放在事件调度线程中。串行端口的配置、打开和读取发生在 doInBackground() 方法。读取是一个无休止的while循环,它嵌入到另一个while循环中,while循环测试 isCancelled() . 通过按下gui中的按钮来触发取消操作。
textarea和控制台中的输出发生在 process() 方法。这个 done() 方法只需启用/禁用gui元素并存储printwriter close() 方法。
在文件中写入时,我使用filewriter/printwriter(在 process() 方法)。
结果:我得到了文件中最后发送的一行。忽略previos发送行(仅在文件中)。e、 g.我通过终端程序通过串行连接发送“一”“二”“三”(line end=lf,cr或cr lf没有区别)。我刚收到文件里的第三行。在gui和控制台上,我收到了预期的完整的3个字符串。
我的相关缩短代码(github的完整代码,分支“logfile”):

public class SerialPrinter extends JFrame {

    PrintWriter pw;

    private class SerialReadTask extends SwingWorker<Boolean, String> {
        protected Boolean doInBackground() {
            // [Omitted code] Get values from the GUI an open serial port ....
            // Reading serial data
            Scanner serialScanner = new Scanner(chosenPort.getInputStream());
            while (!isCancelled()) {
                while (serialScanner.hasNextLine()) {
                    String line = serialScanner.nextLine();
                    publish(line);
                }
            }
            return false; // Returns true if cannot open serial port (code not here)
        }

        protected void process(List<String> chunk) {
            try {
                pw = new PrintWriter(new FileWriter(tf_Logfile.getText()));
                for (String line : chunk) {
                    pw.println(line); // save to file
                    ta_VirtualPrint.append(line + "\n"); // display in GUI => WORKS!!!
                    System.out.println(line); // print on console => WORKS!!!
                }
            } catch (IOException ex) {
            }
        }

        protected void done() {
            // [Omitted code] Disabling some GUI elemts. Usage of get()<Boolean>    
            if (pw != null) { // if PrintWriter bw exists
                pw.close(); // Close but just get the last submitted line in the file
            }
        }

        private void btn_OpenPortActionPerformed(ActionEvent e) [
            serialReader.execute()
        }

        private void btn_ClosePortActionPerformed(ActionEvent e) [
            serialReader.cancel()
        }
}

希望你有个主意。先谢谢你,
哈尼语

wlsrxk51

wlsrxk511#

你在打电话吗 publish 对于每条线:

publish(line);

所以每次文件被一行覆盖,最后一行被写入。
您可以考虑填充 List<String> 将所有读取行,然后将列表转换为数组,并调用 publish 用这个数组。

while (!isCancelled()) {

        List<String> data = new ArrayList<String>();

        while (serialScanner.hasNextLine()) {
            String line = serialScanner.nextLine();
            data.add(line);
        }

        publish(data.toArray(new String[data.size()]));
    }

或者,您可以保持代码的原样,只需创建 FileWriter 在附加模式下:

pw = new PrintWriter(new FileWriter(tf_Logfile.getText(), true));
hsvhsicv

hsvhsicv2#

我将file/printwriter放在后台任务中,而不是edt(progress())任务中,请参见下面的代码。添加的行标记为 // NEW :

protected Boolean doInBackground() throws IOException { // NEW Exception 
            // [Omitted code] Get values from the GUI an open serial port ....
            // Reading serial data
            pw = new PrintWriter(new FileWriter(tf_Logfile.getText())); // NEW
            Scanner serialScanner = new Scanner(chosenPort.getInputStream());
            while (!isCancelled()) {
                while (serialScanner.hasNextLine()) {
                    String line = serialScanner.nextLine();
                    publish(line);
                    pw.println(line); // NEW
                }
            }
            return false; // Returns true if cannot open serial port (code not here)
        }

这个 pw.close() 仍然发生在 done() 方法。
无论如何,正如我之前提到的,这看起来或多或少是一种解决方法,因为我还不明白为什么第一种方法不适用于文件,而适用于屏幕输出。
总之,在som重构=>github之后

相关问题