diff --git a/src/main/java/edu/unl/cse/csv_io/CSVReaderWriter.java b/src/main/java/edu/unl/cse/csv_io/CSVReaderWriter.java index 5af2dac2925917def88cdd30e9e69b1388ad1b64..90d7e477b3c9eb2631acf018f586cf77be5ecbfe 100644 --- a/src/main/java/edu/unl/cse/csv_io/CSVReaderWriter.java +++ b/src/main/java/edu/unl/cse/csv_io/CSVReaderWriter.java @@ -11,8 +11,6 @@ import java.util.*; public class CSVReaderWriter { // this does not (yet) handle data elements that include commas and/or are surrounded by quotation marks - // use of ClassLoader.getResourceAsStream inspired by https://www.mkyong.com/java/java-read-a-file-from-resources-folder/ - // use of Map inspired by Python's csv module private static final String DELIMTER = ","; private static final char BYTE_ORDER_MARK = '\ufeff'; @@ -34,26 +32,7 @@ public class CSVReaderWriter { if (resource != null) { File file = new File(resource.getPath()); try(OutputStream outputStream = new FileOutputStream(file)) { - PrintStream writer = new PrintStream(outputStream); - Set<String> fieldNames = null; - int number_of_fields = 0; - for (Map<String, String> row: data) { - int field_number = 0; - if (fieldNames == null) { - fieldNames = row.keySet(); - number_of_fields = fieldNames.size(); - for (String field: fieldNames) { - writer.print(field); - writer.print(++field_number<number_of_fields ? "," : "\n"); - } - } - field_number = 0; - for (String field: fieldNames) { - String value = row.get(field); - writer.print(value != null ? value : ""); - writer.print(++field_number<number_of_fields ? "," : "\n"); - } - } + placeCSVonStream(data, outputStream); } catch (FileNotFoundException fileNotFoundException) { System.err.println("Could not open " + filename + "; probably due to a bad pathname. " + fileNotFoundException); wroteFile = false; @@ -68,7 +47,7 @@ public class CSVReaderWriter { return wroteFile; } - private static Set<Map<String, String>> parseCSV(InputStream inputStream) throws IOException { + static Set<Map<String, String>> parseCSV(InputStream inputStream) throws IOException { Set<Map<String, String>> csvSet = new HashSet<>(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); String line; @@ -94,22 +73,34 @@ public class CSVReaderWriter { return csvSet; } - public static void main(String[] args) { - Set<Map<String, String>> demo = readCSV("demo.csv"); - boolean success = writeCSV("out.csv", demo); - System.out.println(success ? "Wrote file!" : "Didn't write file"); - /* + static void placeCSVonStream(Set<Map<String, String>> data, OutputStream outputStream) { + PrintStream writer = new PrintStream(outputStream); Set<String> fieldNames = null; - for (Map<String, String> row: demo) { + int number_of_fields = 0; + for (Map<String, String> row: data) { + int field_number = 0; if (fieldNames == null) { fieldNames = row.keySet(); + number_of_fields = fieldNames.size(); + for (String field: fieldNames) { + writer.print(field); + writer.print(++field_number<number_of_fields ? "," : "\n"); + } } + field_number = 0; for (String field: fieldNames) { String value = row.get(field); - System.out.print(field + ":" + value + "\t"); + writer.print(value != null ? value : ""); + writer.print(++field_number<number_of_fields ? "," : "\n"); } - System.out.println(); } - */ } + +/* + public static void main(String[] args) { + Set<Map<String, String>> demo = readCSV("demo.csv"); + boolean success = writeCSV("out.csv", demo); + System.out.println(success ? "Wrote file!" : "Didn't write file"); + } +*/ } diff --git a/src/main/resources/csv/demo.csv b/src/main/resources/csv/demo.csv index fd9504d05f001d24158c9a2526145cda071edd3e..8e1318e6a4a16734c6827d08cb6a50f230652e99 100644 --- a/src/main/resources/csv/demo.csv +++ b/src/main/resources/csv/demo.csv @@ -1,4 +1,4 @@ -A, B, C, D +A,B,C,D one,two,,three four,,five,six 7,8,9, diff --git a/src/test/java/edu/unl/cse/csv_io/CSVReaderWriterTest.java b/src/test/java/edu/unl/cse/csv_io/CSVReaderWriterTest.java new file mode 100644 index 0000000000000000000000000000000000000000..5b8641b2475ff8ae3dbef6303d849dc75158bb17 --- /dev/null +++ b/src/test/java/edu/unl/cse/csv_io/CSVReaderWriterTest.java @@ -0,0 +1,169 @@ +package edu.unl.cse.csv_io; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.*; +import java.util.*; + +import static org.junit.Assert.*; +import static org.hamcrest.CoreMatchers.*; + +public class CSVReaderWriterTest { + private static InputStream inputStream; + private static OutputStream outputStream; + + private static void placeCSVStringOnInputStream(String[][] data) { + String CSVString = createCSVString(data); + inputStream = new ByteArrayInputStream(CSVString.getBytes()); + } + + private static String createCSVString(String[][] data) { + StringBuilder stringBuilder = new StringBuilder(); + for (String[] row : data) { + for (String element : row) { + stringBuilder.append(element).append(","); + } + stringBuilder.deleteCharAt(stringBuilder.lastIndexOf(",")); + stringBuilder.append("\n"); + } + return stringBuilder.toString(); + } + + @Before + public void setUp() { + outputStream = new ByteArrayOutputStream(); + } + + @After + public void tearDown() { + } + + @Test + public void testParsing2x2CSV() { + // Input + String[] headers = {"header1", "header2"}; + String[] row = {"datum1", "datum2"}; + String[][] data = {headers, row}; + // Output + placeCSVStringOnInputStream(data); + Set<Map<String, String>> result = null; + try { + result = CSVReaderWriter.parseCSV(inputStream); + } catch (IOException ignored) { + fail(); + } + // Oracle -- Header + Set<String> expectedKeys = new HashSet<>(Arrays.asList(headers)); + // Oracle -- Rows + Map<String, String> expectedRow = new HashMap<>(); + for (int i=0; i<headers.length; i++) { + expectedRow.put(headers[i], row[i]); + } + // Compare + Map<String,String> aRow = (Map<String,String>)result.toArray()[0]; + assertEquals(expectedKeys, aRow.keySet()); + assertTrue(result.contains(expectedRow)); + } + + @Test + public void testParsing2x3CSV() { + // Input + String[] headers = {"header1", "header2"}; + String[][] rows = {{"datum1", "datum2"}, {"datum3", "datum4"}}; + String[][] data = {headers, rows[0], rows[1]}; + // Output + placeCSVStringOnInputStream(data); + Set<Map<String, String>> result = null; + try { + result = CSVReaderWriter.parseCSV(inputStream); + } catch (IOException ignored) { + fail(); + } + // Oracle -- Header + Set<String> expectedKeys = new HashSet<>(Arrays.asList(headers)); + // Oracle -- Rows + Map<String, String>[] expectedRows = new Map[2]; + for (int i = 0; i < expectedRows.length; i++) { + expectedRows[i] = new HashMap<String, String>(); + for (int j = 0; j < headers.length; j++) { + expectedRows[i].put(headers[j], rows[i][j]); + } + } + // Compare + Map<String, String> aRow = (Map<String, String>) result.toArray()[0]; + assertEquals(expectedKeys, aRow.keySet()); + for (Map<String, String> expectedRow: expectedRows) { + assertTrue(result.contains(expectedRow)); + } + } + + @Test + public void testParsingCSVwithOnlyHeaderRow() { + // Input + String[] headers = {"header1", "header2"}; + String[][] data = {headers}; + // Output + placeCSVStringOnInputStream(data); + Set<Map<String, String>> result = null; + try { + result = CSVReaderWriter.parseCSV(inputStream); + } catch (IOException ignored) { + fail(); + } + // Oracle + int expectedResultSize = 0; + // Compare + assertNotNull(result); + assertEquals(expectedResultSize, result.size()); + } + + @Test + public void testParsingEmptyCSV() { + // Input + String[][] data = {}; + // Output + placeCSVStringOnInputStream(data); + Set<Map<String, String>> result = null; + try { + result = CSVReaderWriter.parseCSV(inputStream); + } catch (IOException ignored) { + fail(); + } + // Oracle + int expectedResultSize = 0; + // Compare + assertNotNull(result); + assertEquals(expectedResultSize, result.size()); + } + + // We probably should test malformed CSVs, but this is good enough for students' starter code + + @Test + public void testWriting2x3CSV() { + // Input + String[] headers = {"header1", "header2"}; + String[][] rows = {{"datum1", "datum2"}, {"datum3", "datum4"}}; + Map<String, String>[] inputRows = new Map[2]; + 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[][] data = {headers, rows[0], rows[1]}; + String expectedCSVStringOption1 = createCSVString(data); + Collections.reverse(Arrays.asList(headers)); + Collections.reverse(Arrays.asList(rows[0])); + Collections.reverse(Arrays.asList(rows[1])); + String expectedCSVStringOption2 = createCSVString(data); + // Output + CSVReaderWriter.placeCSVonStream(input, outputStream); + 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