我正在尝试创建一个简单的类来读取 csv 文件并将内容存储在
ArrayList<ArrayList<T>>.
我正在创建一个通用类 CsvReader,以便我可以处理不同类型的数据:int、double、String。比如说,如果我有一个 double 的 csv 文件,我想我会像这样使用我的类:
//possible method 1
CsvReader<Double> reader = new CsvReader<Double>();
ArrayList<ArrayList<Double>> contents = reader.getContents();
//possible method 2
CsvReader reader = new CsvReader(Double.class);
ArrayList<ArrayList<Double>> contents = reader.getContents();
但是方法 1 不起作用,因为类型删除会阻止您编写类似的代码
rowArrayList.add(new T(columnStringValue));
但我什至无法使 Double.class 解决方案中的传递起作用。问题是,真正发生的事情是我需要我的类在具有以下属性的类型上“参数化”(在该词的一般意义上,而不是技术上的 java 泛型意义):它有一个接受单个 String 参数的 ctor 。也就是说,要在 Double csv 文件上创建行 ArrayLists,我需要编写:
StringTokenizer st = new StringTokenizer(line,",");
ArrayList<Double> curRow = new ArrayList<Double>();
while (st.hasMoreTokens()) {
curRow.add(new Double(st.nextToken());
}
传入 Double.class 后,我可以使用
获取其 String ctor Constructor ctor = c.getConstructor(new Class[] {String.class});
但这有两个问题。最重要的是,这是一个通用构造函数,它将返回一个 Object 类型,然后我无法将其向下转换为 Double。其次,我会缺少“类型”检查,因为我要求传入的类具有 String arg 构造函数。
我的问题是:如何正确实现这个通用 CsvReader?
谢谢, 乔纳
最佳答案
我不确定通用 CSV 阅读器是否会如此简单地使用(顺便说一下,创建也如此)。
我想到的第一个问题是:如果 CSV 包含三列:首先是整数,然后是字符串,最后是日期,该怎么办?您将如何使用通用 CSV 阅读器?
无论如何,假设您想要创建一个 CSV 阅读器,其中所有列都具有相同类型。正如您所说,您无法在“接受 String
作为构造函数”的类型上参数化类。 Java 就是不允许这样做。使用反射的解决方案是一个好的开始。但是,如果您的类在其构造函数之一中不采用 String
作为参数怎么办?
在这里你可以有一个替代方案:一个解析器,它将接受你的字符串并返回正确类型的对象。创建一个通用接口(interface),并为您要爬取的类型进行一些实现:
public interface Parser<T> {
T parse(String value);
}
然后,实现:
public class StringParser implements Parser<String> {
public String parse(String value) {
return value;
}
}
然后,您的 CSV 阅读器可以将 Parser
作为其参数之一。然后,它可以使用这个解析器将每个String
转换为Java对象。
通过这个解决方案,您可以摆脱您所使用的不太漂亮的反射。而且您可以转换为任何类型,只需实现一个Parser
即可。
您的阅读器将如下所示:
public CSVReader<T> {
Parser<T> parser;
List<T> getValues() {
// ...
}
}
现在,回到 CSV 文件可以有多种类型的问题,只需稍微改进一下您的阅读器即可。您所需要的只是一个解析器列表(每列一个),而不是解析所有列的解析器。
希望有帮助:-)
关于java - 创建通用 CsvReader,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3746922/