I would like to display a temperature curve over time. I have now read a file, which is CSV-similar, that let me know the time and the temperature indicated. Now I want to use JFreeChart to display an XY graph from the values. The original data of the file looks as follows:
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
The output of time & temperature values (I have separated from the original file) looks like:
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
EDIT: Now I have inserted a DateTimeFormatter in the example from Trashgod: It looks like:
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;
}
The first line of the "CSV" -like file is still displayed 09:02:53,26.25 Then I get a DateTimeParseException: Text '2017-07-12T09:02:53+02:00' could not be parsed at index 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)
Why can not the rest of the file be read nor displayed? ("System.out.println()" should only serve as a control at the end). The DateTimeFomatter is correct, isn´t it?
With your approach, the time to make locally I come no further & the program can not translate. What did I do wrong? How could it work if the direct output
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
is displayed in a chart? I think to split and to transform like I did is okay, isn´t it? Now I have setDateFormatOverride () in the code, but the error message, as well as the output remain the same.
Several problems are evident:
You never add anything to
lines; at a minimum, you'll need something like this:lines.add(line);Instead of
ChartFactory.createXYLineChart(), consider creating a time series:ChartFactory.createTimeSeriesChart(…)The
XYDatasetreturned bycreateDataset()should be aTimeSeriesCollectionto which you add aTimeSeries.In
createDataset(), iterate thoughlines, parse the data fields, and add the values to theTimeSeries.The time values given are most closely modeled by
LocalTime, butTimeSeriesexpects toadd()coordinates defined by aRegularTimePeriodand adouble; see Legacy Date-Time Code concerning the conversion shown below.Note that
TimeSeriesthrowsSeriesExceptionfor duplicate domain values; as a result, only three of the four lines int eh sample input air charted.Instead of replacing the factory supplied
XYLineAndShapeRenderer, get a reference to it for later modification.Alter the chart's size using one of the approaches shown here.
Avoid extending top-level containers line
ApplicationFrame.Construct and manipulate Swing GUI objects only on the event dispatch thread.
Use a try-with-resources statement to ensure that each resource is closed at the end of the statement.
As your actual data contains ISO 8601 dates,
ZonedDateTime.parse()can be used directly; usesetDateFormatOverride()to format the date axis labels; the example below specifies a UTC time zone in ISO 8601 format for easy comparison; comment out the call tosetDateFormatOverride()to see the times in your local time zone.
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;
}
}
来源:https://stackoverflow.com/questions/45166365/read-data-from-csv-file-into-arraylist-and-display-in-xy-chart
