1 package org.djutils.data.csv;
2
3 import java.io.FileReader;
4 import java.io.FileWriter;
5 import java.io.IOException;
6 import java.io.Reader;
7 import java.io.Writer;
8 import java.util.ArrayList;
9 import java.util.List;
10
11 import org.djutils.data.DataColumn;
12 import org.djutils.data.DataRecord;
13 import org.djutils.data.DataTable;
14 import org.djutils.data.ListDataTable;
15 import org.djutils.data.SimpleDataColumn;
16 import org.djutils.data.serialization.TextSerializationException;
17 import org.djutils.data.serialization.TextSerializer;
18 import org.djutils.exceptions.Throw;
19 import org.djutils.primitives.Primitive;
20
21 import com.opencsv.CSVParserBuilder;
22 import com.opencsv.CSVReader;
23 import com.opencsv.CSVReaderBuilder;
24 import com.opencsv.CSVWriter;
25 import com.opencsv.ICSVWriter;
26 import com.opencsv.exceptions.CsvValidationException;
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 public final class CSVData
47 {
48
49
50
51 private CSVData()
52 {
53
54 }
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71 public static void writeData(final Writer writer, final Writer metaWriter, final DataTable dataTable, final char separator,
72 final char quotechar, final char escapechar, final String lineEnd) throws IOException, TextSerializationException
73 {
74
75 CSVWriter csvMetaWriter = null;
76 CSVWriter csvWriter = null;
77 try
78 {
79 csvMetaWriter = new CSVWriter(metaWriter, separator, quotechar, escapechar, lineEnd);
80 csvMetaWriter.writeNext(new String[] { "id", "description", "className" });
81 csvMetaWriter
82 .writeNext(new String[] { dataTable.getId(), dataTable.getDescription(), dataTable.getClass().getName() });
83 for (DataColumn<?> column : dataTable.getColumns())
84 {
85 csvMetaWriter
86 .writeNext(new String[] { column.getId(), column.getDescription(), column.getValueType().getName() });
87 }
88
89
90 TextSerializer<?>[] serializers = new TextSerializer[dataTable.getNumberOfColumns()];
91 for (int i = 0; i < dataTable.getNumberOfColumns(); i++)
92 {
93 DataColumn<?> column = dataTable.getColumns().get(i);
94 serializers[i] = TextSerializer.resolve(column.getValueType());
95 }
96
97
98 csvWriter = new CSVWriter(writer, separator, quotechar, escapechar, lineEnd);
99 csvWriter.writeNext(dataTable.getColumnIds());
100 String[] textFields = new String[dataTable.getNumberOfColumns()];
101 for (DataRecord record : dataTable)
102 {
103 Object[] values = record.getValues();
104 for (int i = 0; i < dataTable.getNumberOfColumns(); i++)
105 {
106 textFields[i] = serializers[i].serialize(values[i]);
107 }
108 csvWriter.writeNext(textFields);
109 }
110 }
111 finally
112 {
113 if (null != csvMetaWriter)
114 {
115 csvMetaWriter.close();
116 }
117 if (null != csvWriter)
118 {
119 csvWriter.close();
120 }
121 }
122 }
123
124
125
126
127
128
129
130
131
132
133
134
135 public static void writeData(final Writer writer, final Writer metaWriter, final DataTable dataTable)
136 throws IOException, TextSerializationException
137 {
138 writeData(writer, metaWriter, dataTable, ICSVWriter.DEFAULT_SEPARATOR, ICSVWriter.DEFAULT_QUOTE_CHARACTER, '\\',
139 ICSVWriter.DEFAULT_LINE_END);
140 }
141
142
143
144
145
146
147
148
149
150 public static void writeData(final String filename, final String metaFilename, final DataTable dataTable)
151 throws IOException, TextSerializationException
152 {
153 FileWriter fw = null;
154 FileWriter mfw = null;
155 try
156 {
157 fw = new FileWriter(filename);
158 mfw = new FileWriter(metaFilename);
159 writeData(fw, mfw, dataTable);
160 }
161 finally
162 {
163 if (null != fw)
164 {
165 fw.close();
166 }
167 if (null != mfw)
168 {
169 mfw.close();
170 }
171 }
172 }
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187 public static DataTable readData(final Reader reader, final Reader metaReader, final char separator, final char quotechar,
188 final char escapechar, final String lineEnd) throws IOException, CsvValidationException, TextSerializationException
189 {
190 CSVReader csvMetaReader = null;
191 CSVReader csvReader = null;
192 try
193 {
194
195 csvMetaReader = new CSVReaderBuilder(metaReader).withCSVParser(
196 new CSVParserBuilder().withSeparator(separator).withQuoteChar(quotechar).withEscapeChar(escapechar).build())
197 .build();
198 List<DataColumn<?>> columns = new ArrayList<>();
199 String[] header = csvMetaReader.readNext();
200 Throw.when(
201 header.length != 3 || !"id".equals(header[0]) || !"description".equals(header[1])
202 || !"className".equals(header[2]),
203 IOException.class, "header of the metafile does not contain 'id, description, className' as fields");
204
205
206 String[] tableLine = csvMetaReader.readNext();
207 Throw.when(tableLine == null, IOException.class, "no table information in the metafile");
208 Throw.when(tableLine.length != 3, IOException.class, "table data in the metafile does not contain 3 fields");
209 Throw.when(!tableLine[2].endsWith("ListDataTable"), IOException.class,
210 "Currently, this method can only recreate a ListDataTable");
211
212
213 String[] line = csvMetaReader.readNext();
214 while (line != null)
215 {
216 Throw.when(line.length != 3, IOException.class, "column data in the metafile does not contain 3 fields");
217 String type = line[2];
218 Class<?> valueClass = Primitive.forName(type);
219 if (valueClass == null)
220 {
221 try
222 {
223 valueClass = Class.forName(type);
224 }
225 catch (ClassNotFoundException exception)
226 {
227 throw new IOException("Could not find class " + type, exception);
228 }
229 }
230 @SuppressWarnings({ "rawtypes", "unchecked" })
231 DataColumn<?> column = new SimpleDataColumn(line[0], line[1], valueClass);
232 columns.add(column);
233 line = csvMetaReader.readNext();
234 }
235
236
237 ListDataTablestDataTable">ListDataTable dataTable = new ListDataTable(tableLine[0], tableLine[1], columns);
238
239
240 TextSerializer<?>[] serializers = new TextSerializer[dataTable.getNumberOfColumns()];
241 for (int i = 0; i < dataTable.getNumberOfColumns(); i++)
242 {
243 DataColumn<?> column = dataTable.getColumns().get(i);
244 serializers[i] = TextSerializer.resolve(column.getValueType());
245 }
246
247
248 csvReader = new CSVReaderBuilder(reader).withCSVParser(
249 new CSVParserBuilder().withSeparator(separator).withQuoteChar(quotechar).withEscapeChar(escapechar).build())
250 .build();
251 header = csvReader.readNext();
252 Throw.when(header.length != columns.size(), IOException.class,
253 "Number of columns in the data file does not match column metadata size");
254 for (int i = 0; i < header.length; i++)
255 {
256 Throw.when(!header[i].equals(columns.get(i).getId()), IOException.class,
257 "Header for column %d in the data file does not match column metadata info", i);
258 }
259
260
261 String[] data = csvReader.readNext();
262 while (data != null)
263 {
264 Object[] values = new Object[columns.size()];
265 for (int i = 0; i < values.length; i++)
266 {
267 values[i] = serializers[i].deserialize(data[i]);
268 }
269 dataTable.addRecord(values);
270 data = csvReader.readNext();
271 }
272 return dataTable;
273 }
274 finally
275 {
276 if (null != csvMetaReader)
277 {
278 csvMetaReader.close();
279 }
280 if (null != csvReader)
281 {
282 csvReader.close();
283 }
284 }
285 }
286
287
288
289
290
291
292
293
294
295
296 public static DataTable readData(final Reader reader, final Reader metaReader)
297 throws IOException, CsvValidationException, TextSerializationException
298 {
299 return readData(reader, metaReader, ICSVWriter.DEFAULT_SEPARATOR, ICSVWriter.DEFAULT_QUOTE_CHARACTER, '\\',
300 ICSVWriter.DEFAULT_LINE_END);
301 }
302
303
304
305
306
307
308
309
310
311
312 public static DataTable readData(final String filename, final String metaFilename)
313 throws IOException, CsvValidationException, TextSerializationException
314 {
315 FileReader fr = null;
316 FileReader mfr = null;
317 try
318 {
319 fr = new FileReader(filename);
320 mfr = new FileReader(metaFilename);
321 return readData(fr, mfr);
322 }
323 finally
324 {
325 if (null != fr)
326 {
327 fr.close();
328 }
329 if (null != mfr)
330 {
331 mfr.close();
332 }
333 }
334 }
335
336 }