Printwriter 多行与 StringBuilder 到 CSV 文件
Printwriter multiple lines with StringBuilder to CSV-file
我有 100 个粒子,它们都在 Timer
和 ActionListener
的帮助下移动。我通过将坐标 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
以获得更好的封装。
我有 100 个粒子,它们都在 Timer
和 ActionListener
的帮助下移动。我通过将坐标 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
以获得更好的封装。