Printwriter 多行与 StringBuilder 到 CSV 文件

Printwriter multiple lines with StringBuilder to CSV-file

我有 100 个粒子,它们都在 TimerActionListener 的帮助下移动。我通过将坐标 x,y 保存在 StringBuilder 中来跟踪粒子的运动。该过程完成后,我尝试将结果打印到 CSV 文件中,输出如下所示;

time1, x1, y1, x2, y2, ... , xn, yn time2, x1, y1, x2, y2, ... , xn, yn,在粒子移动 100 次后计时器停止的那一刻,我在 ActionListener 中使用了一个计数器来完成这项工作。问题是,我的 CSV 文件中的输出看起来乱七八糟,超过 600 行,它应该只有 100 行。

我试过使用不同的 "newline" 命令,例如 \n\r\n%n,但是其中的 none 给了我 100 行。

我想使用 StringBuilder 而不仅仅是使用 + 的原因是因为我希望代码适用于尽可能多的粒子。如果您有任何其他建议,我很乐意采纳。

Controller:

import javax.swing.event.*;
import java.awt.event.*;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import javax.swing.*;

public class Controller extends JPanel implements ActionListener{
    Model model;
    View view;
    private Timer timer;
    private int delta = 100;
    private StringBuilder csv = new StringBuilder();
    private int counter = 0;
    private int time = 2000;

    public Controller(Model m, View v) {
        model = m;
        view = v;
        timer = new Timer(delta, this);
        timer.setInitialDelay(time);
        timer.start();
    }

    public void actionPerformed(ActionEvent arg0) {
        counter++;

        csv.append(time);
        csv.append(",");
        csv.append(model.getPos());
        csv.append("\n");

        model.updatePos();
        view.repaint();
        time += delta * 0.001;

        if (counter>100) {
            timer.stop();
            PrintWriter pw;
            try {
                pw = new PrintWriter("data.csv");
                pw.println(csv);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
    }
}

Model:

import java.util.ArrayList;

public class Model {
    public int numberofparticles;
    public ArrayList<Particle> particlelist;
    public StringBuilder position = new StringBuilder();

    Model() {
        particlelist = new ArrayList<Particle>();
        numberofparticles = 100;
        for (int i = 0; i < numberofparticles; i++) {
            particlelist.add(new Particle());
        }
    }

    public void updatePos() {
        for (int i = 0; i < numberofparticles; i++) {
        particlelist.get(i).x += 2*Math.cos(Math.random()*2*Math.PI);
        particlelist.get(i).y += 2*Math.sin(Math.random()*2*Math.PI);
        }
    }

    public StringBuilder getPos() {
        for (int i=0; i < numberofparticles; i++) {
            //position.setLength(0);
            position.append(particlelist.get(i).x);
            position.append(",");
            position.append(particlelist.get(i).y);
            position.append(",");
        }
        return position;
    }

    public class Particle {
        private double x;
        private double y;

        public Particle(double setX,double setY) {
            x = setX;
            y = setY;
        }

        Particle() {
            this(500+250*2*Math.cos(Math.random()*2*Math.PI),
                 300+150*2*Math.sin(Math.random()*2*Math.PI));
        }

        public double getX() {
            return x;
        }

        public double getY() {
            return y;
        }
    }
}

View:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.*;

public class View extends JPanel{
    Model model;

    View(Model m){
        model = m;
        this.setPreferredSize(new Dimension(1010,610));
    }

    public void paint(Graphics g) {
        g.setColor(Color.DARK_GRAY);
        for (int i=0; i < model.numberofparticles; i++) {
        g.fillOval((int)(model.particlelist.get(i).getX()), (int) (model.particlelist.get(i).getY()), 3, 3);
        }
    }
}

MyFrame:

import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.JFrame;

public class MyFrame extends JFrame{
    Model model;
    View view;

    MyFrame() {
        Model model = new Model();
        View view = new View(model);
        Controller control = new Controller(model, view);

        this.setBackground(Color.ORANGE);
        this.add(BorderLayout.NORTH, control);
        this.add(view);
        this.pack();
        this.setVisible(true);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public static void main( String[] args ) {
        new MyFrame();
    }
}

编辑: 上面的代码现已完成,可以复制粘贴以重现错误。

Model 中,我注释掉了一行,它会在每个 运行 之后重置 StringBuilder,但是如果我使用这一行,那么数据输出到 CSV 只是变得一无所有。我不知道为什么。

未经测试,我认为错误是 StringBuilder position 是模型中的一个字段。在您的代码中,每次调用 getPos() 都会向同一个字符串生成器添加更多内容。相反,getPos() 应该首先创建一个新的字符串生成器,并在向其添加坐标的同时将其保存在本地。

另外 %n in StringBuilder.append() 永远不会给你一个换行符。 '\n'"\r\n"System.getProperty("line.separator") 都可以,最后一个最正确。

顺便说一句,模型的字段应该是public吗?我认为您可以安全地声明它们 private 以获得更好的封装。