javalist

Java read several kinds of csv file into list


I've written below codes. I am wondering if there is better way of doing this. My abstract class to read csv file.

public abstract class CsvFile {

public void readCsv(String csvString) throws IllegalAccessException {

    String[] csv = csvString.split(",");
    List<Field> fields = Arrays.stream(getClass().getDeclaredFields())
            .filter(f -> f.isAnnotationPresent(CsvProp.class))
            .sorted(Comparator.comparing(o -> Integer.parseInt(o.getName().replaceAll("[^0-9]", ""))))
            .collect(Collectors.toList());

    for (int i = 0; i < fields.size(); i++) {
        Field field = fields.get(i);
        try {
            field.set(this, csv[i]);
        } catch (IndexOutOfBoundsException e) {
            field.set(this, "");
        }
    }
}

And classes that extends it.

    public class CsvType1 extends CsvFile {

    @CsvProp(name = "csvItem1")
    public String item1;

    @CsvProp(name = "csvItem2")
    public String item2;
}

public class CsvType2 extends CsvFile {

    @CsvProp(name = "csvItem1")
    public String item1;

    @CsvProp(name = "csvItem2")
    public String item2;

    @CsvProp(name = "csvItem3")
    public String item3;
}

And utility class to read file.

public class CsvUtils {
    public static List<CsvFile> readCsvFile(Class<? extends CsvFile> fileClass, String filePath) throws IOException, ReflectiveOperationException {
    List<CsvFile> list = new ArrayList<>();
    try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
        String line;
        while ((line = br.readLine()) != null) {
            CsvFile csvFile = fileClass.getConstructor().newInstance();
            csvFile.readCsv(line);
            list.add(csvFile);
        }
        return list;
    }
}

Usage:

    public static void main(String[] args) throws IOException, ReflectiveOperationException {
    List<CsvFile> f1 = CsvUtils.readCsvFile(CsvType1.class, "C:/csvfile1.csv");
    List<CsvFile> f2 = CsvUtils.readCsvFile(CsvType2.class, "C:/csvfile2.csv");

    for (CsvFile f : f1) {
        CsvType1 castedF = (CsvType1) f;
        System.out.println(castedF.item1);
    }
}

Is there a way to use it without casting by changing return type? I want use like this:

    List<CsvType1> f1 = CsvUtils.readCsvFile(CsvType1.class, "C:/csvfile1.csv");

for (CsvType1 noCastF : f1) {
    System.out.println(noCastF.item1);
}

Solution

  • Use

    public static <T extends CsvFile> List<T> readCsvFile(Class<T> fileClass, String filePath) throws IOException, ReflectiveOperationException 
    

    Also. Why not use existing library? Your is not proper csv parser.