diff --git a/pom.xml b/pom.xml
index ce4dc4876f751cdd8faf12155897ce829e59af36..66b30af2a96f993e6cb5de71700c40937f10f935 100644
--- a/pom.xml
+++ b/pom.xml
@@ -31,7 +31,7 @@
                     <archive>
                         <manifest>
                             <addClasspath>true</addClasspath>
-                            <mainClass>edu.unl.cse.csv_io.CSVReaderWriter</mainClass>
+                            <mainClass>edu.unl.cse.csv_io.CsvFile</mainClass>
                         </manifest>
                     </archive>
                 </configuration>
diff --git a/src/main/java/edu/unl/cse/csv_io/AbstractFormattedFile.java b/src/main/java/edu/unl/cse/csv_io/AbstractFormattedFile.java
new file mode 100644
index 0000000000000000000000000000000000000000..bb5a1c8384ba2e2b113b810f2a8a3f7873309705
--- /dev/null
+++ b/src/main/java/edu/unl/cse/csv_io/AbstractFormattedFile.java
@@ -0,0 +1,29 @@
+package edu.unl.cse.csv_io;
+
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+public abstract class AbstractFormattedFile implements FormattedFile {
+    protected final String filename;
+    private Set<String> fields;
+
+    protected AbstractFormattedFile(String filename) {
+        this.filename = filename;
+        fields = new LinkedHashSet<>();
+    }
+
+    public Set<String> getFields() {
+        return Collections.unmodifiableSet(fields);
+    }
+
+    @SuppressWarnings("unused")
+    protected boolean addField(String fieldName) {
+        return fields.add(fieldName);
+    }
+
+    @SuppressWarnings("UnusedReturnValue")
+    protected boolean addAllFields(Set<String> possiblyNewFields) {
+        return fields.addAll(possiblyNewFields);
+    }
+}
diff --git a/src/main/java/edu/unl/cse/csv_io/CSVReaderWriter.java b/src/main/java/edu/unl/cse/csv_io/CsvFile.java
similarity index 73%
rename from src/main/java/edu/unl/cse/csv_io/CSVReaderWriter.java
rename to src/main/java/edu/unl/cse/csv_io/CsvFile.java
index 2e30ffc45a5f10da27c0187413f82cd3edb53461..565498b7acc611e9df8fb07d96c64a1efb1f5a59 100644
--- a/src/main/java/edu/unl/cse/csv_io/CSVReaderWriter.java
+++ b/src/main/java/edu/unl/cse/csv_io/CsvFile.java
@@ -14,27 +14,20 @@ import java.net.URL;
 import java.util.*;
 
 @SuppressWarnings("unused")
-public class CSVReaderWriter {
-
-    @SuppressWarnings("WeakerAccess")
-    public static Set<Map<String, String>> readCSVasSet(String filename) {
-        Set<Map<String, String>> csvSet = null;
-        try (InputStreamReader inputStreamReader = new InputStreamReader(Objects.requireNonNull(
-                CSVReaderWriter.class.getClassLoader().getResourceAsStream("csv/" + filename)))) {
-            csvSet = (Set<Map<String, String>>) parseCSV(inputStreamReader, new HashSet<>());
-        } catch (NullPointerException nullPointerException) {
-            System.err.println("Check spelling of file " + filename + ".");
-        } catch (IOException ioException) {
-            System.err.println("Error loading " + filename + ".  " + ioException);
-        }
-        return csvSet;
+public class CsvFile extends AbstractFormattedFile implements FormattedFile {
+    CsvFile(String filename) {
+        super("csv/" + filename + ".csv");
     }
 
-    public static List<Map<String, String>> readCSVasList(String filename) {
+    @Override
+    public Collection<Map<String, String>> readFile() {
         List<Map<String, String>> csvList = null;
         try (InputStreamReader inputStreamReader = new InputStreamReader(Objects.requireNonNull(
-                CSVReaderWriter.class.getClassLoader().getResourceAsStream("csv/" + filename)))) {
+                CsvFile.class.getClassLoader().getResourceAsStream(filename)))) {
             csvList = (List<Map<String, String>>) parseCSV(inputStreamReader, new LinkedList<>());
+            for(Map<String,String> row:csvList) {
+                addAllFields(row.keySet());
+            }
         } catch (NullPointerException nullPointerException) {
             System.err.println("Check spelling of file " + filename + ".");
         } catch (IOException ioException) {
@@ -43,8 +36,7 @@ public class CSVReaderWriter {
         return csvList;
     }
 
-    private static Collection<Map<String, String>> parseCSV(Reader reader,
-                                                            Collection<Map<String, String>> destination) {
+    Collection<Map<String, String>> parseCSV(Reader reader, Collection<Map<String, String>> destination) {
         Map<String, String> line;
         try {
             CSVReaderHeaderAware csvReader = new CSVReaderHeaderAwareBuilder(reader).build();
@@ -61,9 +53,10 @@ public class CSVReaderWriter {
         return destination;
     }
 
-    public static boolean writeCSV(String filename, Collection<Map<String, String>> data) {
+    @Override
+    public boolean writeFile(Collection<Map<String, String>> data) {
         boolean wroteFile = true;
-        ClassLoader classLoader = CSVReaderWriter.class.getClassLoader();
+        ClassLoader classLoader = CsvFile.class.getClassLoader();
         URL resource = classLoader.getResource("csv/" + filename);
         if (resource == null) {
             try {
@@ -94,7 +87,7 @@ public class CSVReaderWriter {
         return wroteFile;
     }
 
-    static void placeCSVonWriter(Collection<Map<String, String>> data, Writer writer) {
+    void placeCSVonWriter(Collection<Map<String, String>> data, Writer writer) {
         CSVWriter csvWriter = new CSVWriter(writer);
         List<String[]> allLines = new LinkedList<>();
         String[] fieldNames = getFieldNames(data);
@@ -112,12 +105,11 @@ public class CSVReaderWriter {
         csvWriter.writeAll(allLines, false);
     }
 
-    private static String[] getFieldNames(Collection<Map<String, String>> data) {
-        Set<String> fieldNames = new HashSet<>();
+    private String[] getFieldNames(Collection<Map<String, String>> data) {
         for (Map<String, String> row : data) {
-            fieldNames.addAll(row.keySet());
+            addAllFields(row.keySet());
         }
-        List<String> fieldList = new ArrayList<>(fieldNames);
+        List<String> fieldList = new ArrayList<>(getFields());
         String[] fieldArray = new String[fieldList.size()];
         fieldArray = fieldList.toArray(fieldArray);
         return fieldArray;
@@ -176,27 +168,4 @@ public class CSVReaderWriter {
         collection.addAll(preliminaryCollection);
         return collection;
     }
-
-    /* LEGACY METHODS */
-    public static Set<Map<String, String>> readCSV(String filename) {
-        return readCSVasSet(filename);
-    }
-
-    static Set<Map<String, String>> parseCSV(InputStream inputStream) {
-        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) {
-        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/java/edu/unl/cse/csv_io/FormattedFile.java b/src/main/java/edu/unl/cse/csv_io/FormattedFile.java
new file mode 100644
index 0000000000000000000000000000000000000000..fa19088cc9e5daa23e954570bb91bbc7aef73cff
--- /dev/null
+++ b/src/main/java/edu/unl/cse/csv_io/FormattedFile.java
@@ -0,0 +1,13 @@
+package edu.unl.cse.csv_io;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+@SuppressWarnings("unused")
+public interface FormattedFile {
+    // TODO: change from Map<String,String> to Map<String,Object>, where Object is constrained to String, Long, Boolean, or List<String>
+    Collection<Map<String, String>> readFile();
+    boolean writeFile(Collection<Map<String, String>> data);
+    Set<String> getFields();
+}
diff --git a/src/test/java/edu/unl/cse/csv_io/CSVReaderWriterTest.java b/src/test/java/edu/unl/cse/csv_io/CsvFileTest.java
similarity index 86%
rename from src/test/java/edu/unl/cse/csv_io/CSVReaderWriterTest.java
rename to src/test/java/edu/unl/cse/csv_io/CsvFileTest.java
index 64f27c3a66b5eb28cb5514cad035bc1f844ac922..54122b2119ec47ef50471fad765b99f214dcf751 100644
--- a/src/test/java/edu/unl/cse/csv_io/CSVReaderWriterTest.java
+++ b/src/test/java/edu/unl/cse/csv_io/CsvFileTest.java
@@ -11,14 +11,15 @@ import static org.junit.Assert.*;
 import static org.hamcrest.CoreMatchers.*;
 
 @SuppressWarnings("unchecked") // pee-yew!
-public class CSVReaderWriterTest {
-    private static InputStream inputStream;
+public class CsvFileTest {
     private static OutputStream outputStream;
+    private static Reader reader;
     private static Writer writer;
+    private CsvFile csvFile;
 
     private static void placeCSVStringOnInputStream(String[][] data) {
         String CSVString = createCSVString(data);
-        inputStream = new ByteArrayInputStream(CSVString.getBytes());
+        reader = new InputStreamReader(new ByteArrayInputStream(CSVString.getBytes()));
     }
 
     private static String createCSVString(String[][] data) {
@@ -37,6 +38,7 @@ public class CSVReaderWriterTest {
     public void setUp() {
         outputStream = new ByteArrayOutputStream();
         writer = new OutputStreamWriter(outputStream);
+        csvFile = new CsvFile("");
     }
 
     @After
@@ -53,8 +55,8 @@ public class CSVReaderWriterTest {
         String[][] data = {headers, row};
         // Output
         placeCSVStringOnInputStream(data);
-        Set<Map<String, String>> result;
-        result = CSVReaderWriter.parseCSV(inputStream);
+        Collection<Map<String, String>> result;
+        result = csvFile.parseCSV(reader, new HashSet<>());
         // Oracle -- Header
         Set<String> expectedKeys = new HashSet<>(Arrays.asList(headers));
         // Oracle -- Rows
@@ -77,8 +79,8 @@ public class CSVReaderWriterTest {
         String[][] data = {headers, rows[0], rows[1]};
         // Output
         placeCSVStringOnInputStream(data);
-        Set<Map<String, String>> result;
-        result = CSVReaderWriter.parseCSV(inputStream);
+        Collection<Map<String, String>> result;
+        result = csvFile.parseCSV(reader, new HashSet<>());
         // Oracle -- Header
         Set<String> expectedKeys = new HashSet<>(Arrays.asList(headers));
         // Oracle -- Rows
@@ -105,8 +107,8 @@ public class CSVReaderWriterTest {
         String[][] data = {headers};
         // Output
         placeCSVStringOnInputStream(data);
-        Set<Map<String, String>> result;
-        result = CSVReaderWriter.parseCSV(inputStream);
+        Collection<Map<String, String>> result;
+        result = csvFile.parseCSV(reader, new HashSet<>());
         // Oracle
         int expectedResultSize = 0;
         // Compare
@@ -120,8 +122,8 @@ public class CSVReaderWriterTest {
         String[][] data = {};
         // Output
         placeCSVStringOnInputStream(data);
-        Set<Map<String, String>> result;
-        result = CSVReaderWriter.parseCSV(inputStream);
+        Collection<Map<String, String>> result;
+        result = csvFile.parseCSV(reader, new HashSet<>());
         // Oracle
         int expectedResultSize = 0;
         // Compare
@@ -137,8 +139,8 @@ public class CSVReaderWriterTest {
         String[][] data = {headers, rows[0], rows[1], rows[2]};
         // Output
         placeCSVStringOnInputStream(data);
-        Set<Map<String, String>> result;
-        result = CSVReaderWriter.parseCSV(inputStream);
+        Collection<Map<String, String>> result;
+        result = csvFile.parseCSV(reader, new HashSet<>());
         // Oracle -- Header
         Set<String> expectedKeys = new HashSet<>(Arrays.asList(headers));
         // Oracle -- Rows
@@ -181,7 +183,8 @@ public class CSVReaderWriterTest {
         Collections.reverse(Arrays.asList(rows[1]));
         String expectedCSVStringOption2 = createCSVString(data);
         // Output
-        CSVReaderWriter.placeCSVonStream(input, outputStream);
+        csvFile.placeCSVonWriter(input, writer);
+        writer.flush();
         String output = outputStream.toString();
         // Compare
         assertTrue(expectedCSVStringOption1.equals(output) || expectedCSVStringOption2.equals(output));
@@ -210,7 +213,7 @@ public class CSVReaderWriterTest {
         Collections.reverse(Arrays.asList(formattedRow2));
         String expectedCSVStringOption2 = createCSVString(data);
         // Output
-        CSVReaderWriter.placeCSVonWriter(input, writer);
+        csvFile.placeCSVonWriter(input, writer);
         writer.flush();
         String output = outputStream.toString();
         // Compare
@@ -226,7 +229,7 @@ public class CSVReaderWriterTest {
         // Oracle
         String expectedOutput = "foo bar \"baz plugh\"";
         // Output
-        String actualOutput = CSVReaderWriter.createDelimitedCollection(inputList, " ");
+        String actualOutput = CsvFile.createDelimitedCollection(inputList, " ");
         // Compare
         assertEquals(expectedOutput, actualOutput);
     }
@@ -239,7 +242,7 @@ public class CSVReaderWriterTest {
         // Oracle
         String expectedOutput = "foo";
         // Output
-        String actualOutput = CSVReaderWriter.createDelimitedCollection(input, " ");
+        String actualOutput = CsvFile.createDelimitedCollection(input, " ");
         // Compare
         assertEquals(expectedOutput, actualOutput);
     }
@@ -251,7 +254,7 @@ public class CSVReaderWriterTest {
         // Oracle
         String expectedOutput = "";
         // Output
-        String actualOutput = CSVReaderWriter.createDelimitedCollection(input, " ");
+        String actualOutput = CsvFile.createDelimitedCollection(input, " ");
         // Compare
         assertEquals(expectedOutput, actualOutput);
     }
@@ -264,7 +267,7 @@ public class CSVReaderWriterTest {
         String[] expectedOutputArray = {"one", "two", "three", "four"};
         Collection<String> expectedOutput = Arrays.asList(expectedOutputArray);
         // Output
-        Collection<String> actualOutput = CSVReaderWriter.createFreeCollection(input, " ", new ArrayList<>());
+        Collection<String> actualOutput = CsvFile.createFreeCollection(input, " ", new ArrayList<>());
         // Compare
         assertEquals(expectedOutput, actualOutput);
     }
@@ -277,7 +280,7 @@ public class CSVReaderWriterTest {
         String[] expectedOutputArray = {"one"};
         Collection<String> expectedOutput = Arrays.asList(expectedOutputArray);
         // Output
-        Collection<String> actualOutput = CSVReaderWriter.createFreeCollection(input, " ", new ArrayList<>());
+        Collection<String> actualOutput = CsvFile.createFreeCollection(input, " ", new ArrayList<>());
         // Compare
         assertEquals(expectedOutput, actualOutput);
     }
@@ -289,7 +292,7 @@ public class CSVReaderWriterTest {
         // Oracle
         Collection<String> expectedOutput = new ArrayList<>();
         // Output
-        Collection<String> actualOutput = CSVReaderWriter.createFreeCollection(input, " ", new ArrayList<>());
+        Collection<String> actualOutput = CsvFile.createFreeCollection(input, " ", new ArrayList<>());
         // Compare
         assertEquals(expectedOutput, actualOutput);
         assertNotNull(actualOutput);
@@ -303,7 +306,7 @@ public class CSVReaderWriterTest {
         // Oracle
         Collection<String> expectedOutput = new ArrayList<>();
         // Output
-        Collection<String> actualOutput = CSVReaderWriter.createFreeCollection(input, " ", new ArrayList<>());
+        Collection<String> actualOutput = CsvFile.createFreeCollection(input, " ", new ArrayList<>());
         // Compare
         assertEquals(expectedOutput, actualOutput);
         assertNotNull(actualOutput);
@@ -318,7 +321,7 @@ public class CSVReaderWriterTest {
         String[] expectedOutputArray = {"one", "two", "three", "four", "five", "six"};
         Collection<String> expectedOutput = Arrays.asList(expectedOutputArray);
         // Output
-        Collection<String> actualOutput = CSVReaderWriter.createFreeCollection(input, " ", new ArrayList<>());
+        Collection<String> actualOutput = CsvFile.createFreeCollection(input, " ", new ArrayList<>());
         // Compare
         assertEquals(expectedOutput, actualOutput);
     }
@@ -331,7 +334,7 @@ public class CSVReaderWriterTest {
         String[] expectedOutputArray = {"one", "two three", "four five", "six"};
         Collection<String> expectedOutput = Arrays.asList(expectedOutputArray);
         // Output
-        Collection<String> actualOutput = CSVReaderWriter.createFreeCollection(input, " ", new ArrayList<>());
+        Collection<String> actualOutput = CsvFile.createFreeCollection(input, " ", new ArrayList<>());
         // Compare
         assertEquals(expectedOutput, actualOutput);
     }
@@ -344,7 +347,7 @@ public class CSVReaderWriterTest {
         String[] expectedOutputArray = {"one", "two", "three\"", "four", "five", "six"};
         Collection<String> expectedOutput = Arrays.asList(expectedOutputArray);
         // Output
-        Collection<String> actualOutput = CSVReaderWriter.createFreeCollection(input, " ", new ArrayList<>());
+        Collection<String> actualOutput = CsvFile.createFreeCollection(input, " ", new ArrayList<>());
         // Compare
         assertEquals(expectedOutput, actualOutput);
     }