将CSV文件解析为泛型类 - Java泛型

时间:2014-03-09 19:18:34

标签: java generics csv

我正在尝试构建一个将CSV文件解析为Object的通用方法。

我认为我已经达到了目标,但我对Java泛型有点困惑,我还在学习它。

现在我被困在我创建对象的循环中。我正在使用jCSV为我解析。我正在关注他们的文档教程here

我无法弄清楚如何设置beanClass bc = it.next();,因为beanClass在我的项目中不存在作为类,编译错误:cannot find symbol - class beanClass 我该如何解决这个问题?

我知道我可以做一个List<?> beanClassList = csvFileReader.readAll(); 但问题是,在每个CSV文件的第一行,我都有该数据所属的类名。我得到了这个例外,这是有道理的:

Exception in thread "AWT-EventQueue-0" java.lang.NumberFormatException: For input string: "Car"

我的CSV文件是这样的:

ClassName
value,value,value,value,value
value,value,value,value,value
...

这是我的代码:

public String importFromCsvFile(File f) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException
    {
    FileReader fr = new FileReader(f);
    BufferedReader buffReader = new BufferedReader(fr);
    String className = buffReader.readLine();

    buffReader.close();

    //Java reflection to get the Class Object.
    Class beanClass = Class.forName("model." + className);

    Object beanObject = beanClass.newInstance();

    Reader reader = new FileReader(f);

    ValueProcessorProvider provider = new ValueProcessorProvider();
    CSVEntryParser<?> entryParser = new AnnotationEntryParser<>(beanClass, provider);
    CSVReader<?> csvFileReader= new CSVReaderBuilder<>(reader).entryParser((CSVEntryParser<Object>) entryParser).build();

    Iterator<?> it = csvFileReader.iterator();

    while (it.hasNext()) {

        beanClass bc = it.next(); // here is the compilation error

    }
}

这是一个CSV文件示例:

Car
1,BMW,Z3,2000,20-AC-57
2,Mercedes,C4,2010,23-32-VJ
3,Alfa Romeo,A3,1992,XX-XX-XX

3 个答案:

答案 0 :(得分:1)

根据您的意见请查看从CSV文件中读取数据并将其作为键值对存储在地图中的示例代码。

List<Map<String, String>> list = new ArrayList<Map<String, String>>();

BufferedReader reader = new BufferedReader(new FileReader(new File("resources/abc.csv")));

String header = reader.readLine();
String[] keys = header.split(",");
String line = null;
while ((line = reader.readLine()) != null) {
    Map<String, String> map = new HashMap<String, String>();
    String[] values = line.split(",");
    for (int i = 0; i < keys.length; i++) {
        map.put(keys[i], values[i]);
    }
    list.add(map);
}

reader.close();

for(Map<String, String> map:list){
    for(String key:map.keySet()){
        System.out.println(key+":"+map.get(key));
    }
    System.out.println();
}

CSV:

ID,NAME,MODEL,YEAR,NUMBER
1,BMW,Z3,2000,20-AC-57
2,Mercedes,C4,2010,23-32-VJ
3,Alfa Romeo,A3,1992,XX-XX-XX

答案 1 :(得分:1)

你快到了。

public String importFromCsvFile(File f) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException
    {
    FileReader fr = new FileReader(f);
    BufferedReader buffReader = new BufferedReader(fr);
    String className = buffReader.readLine();

    buffReader.close(); // you can also not close it and use buffReader as your reader for the CSV

    //Java reflection to get the Class Object.
    Class beanClass = Class.forName("model." + className);

    Object beanObject = beanClass.newInstance(); // this is never needed

    Reader reader = new FileReader(f); // use buffReader instead of creating a new one

    ValueProcessorProvider provider = new ValueProcessorProvider();
    CSVEntryParser<?> entryParser = new AnnotationEntryParser<>(beanClass, provider);
    CSVReader<?> csvFileReader= new CSVReaderBuilder<>(reader).entryParser((CSVEntryParser<Object>) entryParser).build();

    Iterator<?> it = csvFileReader.iterator();

    while (it.hasNext()) {

        Object obj = it.next(); // obj is an instance of Car with your data
        boolean isCar = obj instanceof Car; // will be true
    }
}

由于您使用,作为分隔符,因此您应考虑使用UK_DEFAULT作为Reader的策略或定义您自己的(默认分隔符为;)。

您还应该继续使用BufferedReader或在策略中指定skipHeader - 否则您Car将被视为可能不是您想要的条目。

答案 2 :(得分:0)

使用泛型,在编译时指定类型(并由编译器检查)。在您的情况下,类型仅在CSV文件中指定,因此在编译时未知。因此,在这种情况下,泛型不是一种可以使用的工具。

您希望通过泛型完成什么?您希望编译器检查什么?

可以做的是使用Class.forName(name).newInstance()创建类的实例(您需要包括包的全名)并使用反射来设置一些属性。但是在编译时你只知道结果是Object