Skip to content
Snippets Groups Projects
Commit 5f07781f authored by Christopher Bohn's avatar Christopher Bohn :thinking:
Browse files

Completed refactor

- Writing to CSV is now done with openCSV calls, and client is
  responsible for lifecycle of injected dependencies (closes #1)
- Because of the openCSV calls, commas within a field are now allowed
  on output, as is enclosing a field in quotes (closes #3)
- Because reading had already been rewritten using openCSV calls,
  reading already could handle quoted fields that contained commas; we
  simply didn't have a test for it until now (closes #2)
parent 3a347692
No related branches found
No related tags found
No related merge requests found
...@@ -43,16 +43,16 @@ public class CSVReaderWriter { ...@@ -43,16 +43,16 @@ public class CSVReaderWriter {
return csvList; return csvList;
} }
private static Collection<Map<String, String>> parseCSV(InputStreamReader inputStreamReader, private static Collection<Map<String, String>> parseCSV(Reader reader,
Collection<Map<String, String>> destination) { Collection<Map<String, String>> destination) {
Map<String, String> line; Map<String, String> line;
try { try {
CSVReaderHeaderAware csvReader = new CSVReaderHeaderAwareBuilder(inputStreamReader).build(); CSVReaderHeaderAware csvReader = new CSVReaderHeaderAwareBuilder(reader).build();
while ((line = csvReader.readMap()) != null) { while ((line = csvReader.readMap()) != null) {
destination.add(line); destination.add(line);
} }
} catch (NullPointerException ignored) { } catch (NullPointerException ignored) {
// CSVReaderHeaderAwareBuilder.build() throws NullPointerException if inputStreamReader is empty // CSVReaderHeaderAwareBuilder.build() throws NullPointerException if reader is empty
} catch (IOException ioException) { } catch (IOException ioException) {
System.err.println("Error reading CSV file. " + ioException); System.err.println("Error reading CSV file. " + ioException);
} catch (CsvValidationException csvValidationException) { } catch (CsvValidationException csvValidationException) {
...@@ -69,8 +69,8 @@ public class CSVReaderWriter { ...@@ -69,8 +69,8 @@ public class CSVReaderWriter {
URL resource = classLoader.getResource("csv/" + filename); URL resource = classLoader.getResource("csv/" + filename);
if (resource != null) { if (resource != null) {
File file = new File(resource.getPath()); File file = new File(resource.getPath());
try (OutputStream outputStream = new FileOutputStream(file)) { try (FileWriter fileWriter = new FileWriter(file)) {
placeCSVonStream(data, outputStream); placeCSVonWriter(data, fileWriter);
} catch (FileNotFoundException fileNotFoundException) { } catch (FileNotFoundException fileNotFoundException) {
System.err.println("Could not open " + filename + "; probably due to a bad pathname. " + fileNotFoundException); System.err.println("Could not open " + filename + "; probably due to a bad pathname. " + fileNotFoundException);
wroteFile = false; wroteFile = false;
...@@ -85,13 +85,7 @@ public class CSVReaderWriter { ...@@ -85,13 +85,7 @@ public class CSVReaderWriter {
return wroteFile; return wroteFile;
} }
static void placeCSVonStream(Collection<Map<String, String>> data, OutputStream outputStream) throws IOException { static void placeCSVonWriter(Collection<Map<String, String>> data, Writer writer) {
OutputStreamWriter writer = new OutputStreamWriter(outputStream);
placeCSVonWriter(data, writer);
writer.close();
}
static void placeCSVonWriter(Collection<Map<String, String>> data, OutputStreamWriter writer) {
CSVWriter csvWriter = new CSVWriter(writer); CSVWriter csvWriter = new CSVWriter(writer);
List<String[]> allLines = new LinkedList<>(); List<String[]> allLines = new LinkedList<>();
String[] fieldNames = getFieldNames(data); String[] fieldNames = getFieldNames(data);
...@@ -129,6 +123,12 @@ public class CSVReaderWriter { ...@@ -129,6 +123,12 @@ public class CSVReaderWriter {
return (Set<Map<String, String>>) parseCSV(new InputStreamReader(inputStream), new HashSet<>()); return (Set<Map<String, String>>) parseCSV(new InputStreamReader(inputStream), new HashSet<>());
} }
static void placeCSVonStream(Collection<Map<String, String>> data, OutputStream outputStream) throws IOException {
OutputStreamWriter writer = new OutputStreamWriter(outputStream);
placeCSVonWriter(data, writer);
writer.close();
}
/* /*
public static void main(String[] args) { public static void main(String[] args) {
Set<Map<String, String>> demo = readCSV("demo.csv"); Set<Map<String, String>> demo = readCSV("demo.csv");
......
...@@ -14,6 +14,7 @@ import static org.hamcrest.CoreMatchers.*; ...@@ -14,6 +14,7 @@ import static org.hamcrest.CoreMatchers.*;
public class CSVReaderWriterTest { public class CSVReaderWriterTest {
private static InputStream inputStream; private static InputStream inputStream;
private static OutputStream outputStream; private static OutputStream outputStream;
private static Writer writer;
private static void placeCSVStringOnInputStream(String[][] data) { private static void placeCSVStringOnInputStream(String[][] data) {
String CSVString = createCSVString(data); String CSVString = createCSVString(data);
...@@ -35,10 +36,13 @@ public class CSVReaderWriterTest { ...@@ -35,10 +36,13 @@ public class CSVReaderWriterTest {
@Before @Before
public void setUp() { public void setUp() {
outputStream = new ByteArrayOutputStream(); outputStream = new ByteArrayOutputStream();
writer = new OutputStreamWriter(outputStream);
} }
@After @After
public void tearDown() { public void tearDown() throws IOException {
writer.close();
outputStream.close();
} }
@Test @Test
...@@ -125,6 +129,36 @@ public class CSVReaderWriterTest { ...@@ -125,6 +129,36 @@ public class CSVReaderWriterTest {
assertEquals(expectedResultSize, result.size()); assertEquals(expectedResultSize, result.size());
} }
@Test
public void testReadingWithComma() {
// Input
String[] headers = {"header1", "header2"};
String[][] rows = {{"datum1", "datum2"}, {"datum3", "datum4"}, {"\"datum5, datum6\"", "datum7 datum8"}};
String[][] data = {headers, rows[0], rows[1], rows[2]};
// Output
placeCSVStringOnInputStream(data);
Set<Map<String, String>> result;
result = CSVReaderWriter.parseCSV(inputStream);
// Oracle -- Header
Set<String> expectedKeys = new HashSet<>(Arrays.asList(headers));
// Oracle -- Rows
String[][] parsedRows = {rows[0], rows[1], {"datum5, datum6", "datum7 datum8"}};
Map<String, String>[] expectedRows = new Map[3];
for (int i = 0; i < expectedRows.length; i++) {
expectedRows[i] = new HashMap<>();
for (int j = 0; j < headers.length; j++) {
expectedRows[i].put(headers[j], parsedRows[i][j]);
}
}
// Compare
assertNotNull(result);
Map<String, String> aRow = (Map<String, String>) result.toArray()[0];
assertEquals(expectedKeys, aRow.keySet());
for (Map<String, String> expectedRow : expectedRows) {
assertTrue(result.contains(expectedRow));
}
}
// We probably should test malformed CSVs, but this is good enough for students' starter code // We probably should test malformed CSVs, but this is good enough for students' starter code
@Test @Test
...@@ -153,4 +187,34 @@ public class CSVReaderWriterTest { ...@@ -153,4 +187,34 @@ public class CSVReaderWriterTest {
assertTrue(expectedCSVStringOption1.equals(output) || expectedCSVStringOption2.equals(output)); assertTrue(expectedCSVStringOption1.equals(output) || expectedCSVStringOption2.equals(output));
assertThat(output, either(is(expectedCSVStringOption1)).or(is(expectedCSVStringOption2))); assertThat(output, either(is(expectedCSVStringOption1)).or(is(expectedCSVStringOption2)));
} }
@Test
public void testWritingWithComma() throws IOException {
// Input
String[] headers = {"header1", "header2"};
String[][] rows = {{"datum1", "datum2"}, {"datum3", "datum4"}, {"datum5, datum6", "datum7 datum8"}};
Map<String, String>[] inputRows = new Map[3];
for (int i = 0; i < inputRows.length; i++) {
inputRows[i] = new HashMap<>(2);
inputRows[i].put(headers[0], rows[i][0]);
inputRows[i].put(headers[1], rows[i][1]);
}
Set<Map<String, String>> input = new HashSet<>(Arrays.asList(inputRows));
// Oracle
String[] formattedRow2 = {"\"datum5, datum6\"", "datum7 datum8"};
String[][] data = {headers, rows[0], rows[1], formattedRow2};
String expectedCSVStringOption1 = createCSVString(data);
Collections.reverse(Arrays.asList(headers));
Collections.reverse(Arrays.asList(rows[0]));
Collections.reverse(Arrays.asList(rows[1]));
Collections.reverse(Arrays.asList(formattedRow2));
String expectedCSVStringOption2 = createCSVString(data);
// Output
CSVReaderWriter.placeCSVonWriter(input, writer);
writer.flush();
String output = outputStream.toString();
// Compare
assertTrue(expectedCSVStringOption1.equals(output) || expectedCSVStringOption2.equals(output));
assertThat(output, either(is(expectedCSVStringOption1)).or(is(expectedCSVStringOption2)));
}
} }
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment