2017-07-18 64 views
0

我想显示一段时间内的温度曲线。我现在读了一个类似CSV的文件,让我知道时间和温度。现在我想使用JFreeChart从这些值中显示一个XY图形。看起来 文件的原始数据如下:从CSV文件读取数据到ArrayList并在XY图中显示

utc,local,celsius 
2017-07-12T07:02:53+00:00,2017-07-12T09:02:53+02:00,26.25 
2017-07-12T08:02:54+00:00,2017-07-12T10:02:54+02:00,26.08 
2017-07-12T09:02:55+00:00,2017-07-12T11:02:55+02:00,25.78 
2017-07-12T10:02:56+00:00,2017-07-12T12:02:56+02:00,25.96 
2017-07-12T10:51:02+00:00,2017-07-12T12:51:02+02:00,26.14 
2017-07-12T10:51:02+00:00,2017-07-12T12:51:02+02:00,26.14 

时间&温度值的输出(I已经从原始文件分开)看起来像:

09:02:53,26.25 
10:02:54,26.08 
11:02:55,25.78 
12:02:56,25.96 
12:51:02,26.14 
12:51:02,26.14 

编辑: 现在我插入创建DateTimeFormatter在例如由trashgold: 它看起来像:

public class Test { 
public static void main(String[] args) { 
    EventQueue.invokeLater(() -> { 
     ApplicationFrame frame = new ApplicationFrame("CSVTest"); 
     Test test = new Test(); 
     frame.add(test.createChart("Temperature profile")); 
     frame.pack(); 
     frame.setLocationRelativeTo(null);; 
     frame.setVisible(true); 
    }); 
} 

private ChartPanel createChart(String chartTitle) { 
    JFreeChart chart = ChartFactory.createTimeSeriesChart(chartTitle, 
     "Time", "Temperature", createDataset(), true, true, false); 
    ChartPanel chartPanel = new ChartPanel(chart); 
    XYPlot plot = chart.getXYPlot(); 
    DateAxis domain = (DateAxis) plot.getDomainAxis(); 
    domain.setDateFormatOverride(DateFormat.getDateInstance()); 
    plot.setBackgroundPaint(Color.WHITE); 
    return chartPanel; 
} 


    private XYDataset createDataset() { 
    TimeSeries series = new TimeSeries("Temperature"); 
    TimeSeriesCollection dataset = new TimeSeriesCollection(series); 
    try (FileReader fr = new FileReader("TestCSV.csv"); 
     BufferedReader br = new BufferedReader(fr)) { 
     String line; 
     br.readLine(); 
     while ((line = br.readLine()) != null) { 
      String[] split = line.split(","); 

      System.out.println(ZonedDateTime.parse(split[1]).format(DateTimeFormatter.ISO_LOCAL_TIME) + "," +split[2]); 
      ZonedDateTime zdt = ZonedDateTime.of(LocalDate.now(),LocalTime.parse(split[0]), ZoneId.systemDefault()); 
      String s = ZonedDateTime.parse(split[0]).format(DateTimeFormatter.ISO_LOCAL_TIME); 

      Second second = new Second(Date.from(zdt.toInstant())); 
      series.add(second, Double.valueOf(split[1])); 
     } 
    } catch (IOException | SeriesException e) { 
     System.err.println("Error: " + e); 
    } 
    return dataset; 
} 

类似“CSV”的文件的第一行仍然显示09:02:53,26.25 然后我得到一个DateTimeParseException:文本'2017-07-12T09:02:53 + 02:00'无法在索引处解析2

Exception in thread "AWT-EventQueue-0" java.time.format.DateTimeParseException: Text '2017-07-12T07:02:53+00:00' could not be parsed at index 2 
at java.time.format.DateTimeFormatter.parseResolved0(Unknown Source) 
at java.time.format.DateTimeFormatter.parse(Unknown Source) 
at java.time.LocalTime.parse(Unknown Source) 
at java.time.LocalTime.parse(Unknown Source) 
at org.jfree.chart.demo.Test.createDataset(Test.java:63) 
at org.jfree.chart.demo.Test.createChart(Test.java:43) 
at org.jfree.chart.demo.Test.lambda$0(Test.java:34) 

为什么文件的其余部分不能被读取和不显示? (“System.out.println”最后只能作为控件使用)。 DateTimeFomatter是正确的,是吗?

随着你的方法,在本地制作的时间我不再来&该程序无法翻译。是什么让我错了?如果直接输出如何可以工作

09:02:53,26.25 
10:02:54,26.08 
11:02:55,25.78 
12:02:56,25.96 
12:51:02,26.14 
12:51:02,26.14 

显示在图表中吗?我认为要像我一样分裂并改造是好的,是不是?现在我在代码中设置了DateFormatOverride(),但错误消息以及输出保持不变。

回答

1

几个问题是显而易见的:

  • 你永远不添加任何lines;至少,你需要这样的事:

    lines.add(line); 
    
  • 相反的ChartFactory.createXYLineChart(),考虑创建一个时间序列:

    ChartFactory.createTimeSeriesChart(…) 
    
  • XYDataset通过createDataset()返回应该是一个TimeSeriesCollection到你添加一个TimeSeries

  • createDataset()中,通过lines迭代,解析数据字段,并将值添加到TimeSeriesTimeSeries鉴于LocalTime最密切建模

  • 的时间值,但是希望通过RegularTimePerioddouble定义add()坐标;有关如下所示的转换,请参阅Legacy Date-Time Code

  • 请注意,TimeSeries针对重复的域值引发SeriesException;结果,只有三条线在样本输入航空图中绘制。

  • 取而代之的是替代工厂提供的XYLineAndShapeRenderer,请参考它以供日后修改。

  • 使用here所示方法之一改变图表的尺寸。

  • 避免延伸顶级容器行ApplicationFrame

  • 构建和操作Swing GUI对象只有event dispatch thread上。

  • 使用try-with-resources statement确保每个资源在语句结束时关闭。

  • 由于您的actual data包含ISO 8601日期,所以可以直接使用ZonedDateTime.parse();使用setDateFormatOverride()来格式化日期轴标签;以下示例指定了ISO 8601格式的UTC时区以便于比较;请拨打setDateFormatOverride()以查看您当地时区的时间。

image

import java.awt.Color; 
import java.awt.EventQueue; 
import java.io.BufferedReader; 
import java.io.FileReader; 
import java.io.IOException; 
import java.text.SimpleDateFormat; 
import java.time.ZonedDateTime; 
import java.util.Date; 
import java.util.TimeZone; 
import org.jfree.chart.ChartFactory; 
import org.jfree.chart.ChartPanel; 
import org.jfree.chart.JFreeChart; 
import org.jfree.chart.axis.DateAxis; 
import org.jfree.chart.plot.XYPlot; 
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; 
import org.jfree.data.general.SeriesException; 
import org.jfree.data.time.Second; 
import org.jfree.data.time.TimeSeries; 
import org.jfree.data.time.TimeSeriesCollection; 
import org.jfree.data.xy.XYDataset; 
import org.jfree.ui.ApplicationFrame; 

/** @see https://stackoverflow.com/a/45173688/230513 */ 
public class CSVTest { 

    public static void main(String[] args) { 
     EventQueue.invokeLater(() -> { 
      ApplicationFrame frame = new ApplicationFrame("CSVTest"); 
      CSVTest test = new CSVTest(); 
      frame.add(test.createChart("Temperature profile")); 
      frame.pack(); 
      frame.setLocationRelativeTo(null);; 
      frame.setVisible(true); 
     }); 
    } 

    private ChartPanel createChart(String chartTitle) { 
     JFreeChart chart = ChartFactory.createTimeSeriesChart(chartTitle, 
      "Time", "Temperature", createDataset(), true, true, false); 
     ChartPanel chartPanel = new ChartPanel(chart); 
     XYPlot plot = chart.getXYPlot(); 
     plot.setBackgroundPaint(Color.WHITE); 
     XYLineAndShapeRenderer r = (XYLineAndShapeRenderer) plot.getRenderer(); 
     r.setBaseShapesVisible(true); 
     DateAxis axis = (DateAxis) plot.getDomainAxis(); 
     SimpleDateFormat df = new SimpleDateFormat("HH:mm:ssX"); 
     df.setTimeZone(TimeZone.getTimeZone("UTC")); 
     axis.setDateFormatOverride(df); 
     return chartPanel; 
    } 

    private XYDataset createDataset() { 
     TimeSeries series = new TimeSeries("Temperature"); 
     TimeSeriesCollection dataset = new TimeSeriesCollection(series); 
     try (FileReader fr = new FileReader("temp.csv"); 
      BufferedReader br = new BufferedReader(fr)) { 
      String line; 
      while ((line = br.readLine()) != null) { 
       String[] s = line.split(","); 
       ZonedDateTime zdt = ZonedDateTime.parse(s[0]); 
       Second second = new Second(Date.from(zdt.toInstant())); 
       series.add(second, Double.valueOf(s[2])); 
      } 
     } catch (IOException | SeriesException e) { 
      System.err.println("Error: " + e); 
     } 
     return dataset; 
    } 
} 
+0

谢谢你的建议。但现在问题是分裂。 “CSV”类似文件被拆分,最后它看起来像“时间和温度”,看起来像这样: 2017-07-12T07:02:53 + 00:00,2017-07-12T09:02: 53 + 02:00,26.25 随着你的方法,在本地制作的时间我不会再来,程序也无法翻译。是什么让我错了? 如果直接输出如何工作: 11:02:55,25.78 12:02:56,25.96 显示在图表中吗?我认为要像我一样分裂并改造是好的,是不是? – LostInTranslate

+0

看起来你需要一个'DateTimeFormatter';所引用的教程有一节关于解析。现在您已经有了一个工作示例,请[编辑](https://stackoverflow.com/posts/45166365/edit)您的问题,以包含显示_actual_数据和您的修订方法的[mcve]。 – trashgod

+0

我有修改的问题,现在编辑添加了相应的错误消息 – LostInTranslate