Java 创建通用CsvReader

Java 创建通用CsvReader,java,Java,我试图创建一个简单的类来读取csv文件并将内容存储在 ArrayList<ArrayList<T>>. 但我甚至不能让双级解决方案通过。问题是真正发生的是,我需要对具有以下属性的类型“参数化”我的类(在该词的一般意义上,而不是技术java泛型意义上):它有一个接受单个字符串参数的ctor。也就是说,要在双csv文件上创建行ArrayList,我需要编写: StringTokenizer st = new StringTokenizer(line,","); Arra

我试图创建一个简单的类来读取csv文件并将内容存储在

ArrayList<ArrayList<T>>.  
但我甚至不能让双级解决方案通过。问题是真正发生的是,我需要对具有以下属性的类型“参数化”我的类(在该词的一般意义上,而不是技术java泛型意义上):它有一个接受单个字符串参数的ctor。也就是说,要在双csv文件上创建行ArrayList,我需要编写:

StringTokenizer st = new StringTokenizer(line,",");
ArrayList<Double> curRow = new ArrayList<Double>();
while (st.hasMoreTokens()) {
 curRow.add(new Double(st.nextToken());
}
但这有两个问题。最重要的是,这是一个通用构造函数,它将返回一个类型对象,我不能将其向下转换为Double。其次,我将缺少“类型”检查,因为我要求传入的类具有字符串arg构造函数

我的问题是:如何正确实现这个通用CsvReader

谢谢,
Jonah

我不确定一个通用的CSV阅读器是否会这么容易使用(顺便说一句,也不知道如何创建)

我想到的第一个问题是:如果CSV包含三列:首先是整数,然后是字符串,最后是日期,该怎么办?您将如何使用通用CSV阅读器

无论如何,让我们假设您想要创建一个CSV阅读器,其中所有列的类型都相同。正如您所说,您不能参数化“接受
字符串作为构造函数”的类型上的类。Java就是不允许这样。使用反射的解决方案是一个良好的开端。但是,如果您的类在其构造函数中没有将
字符串作为参数,该怎么办

在这里,您可以使用另一种选择:一个解析器,它将接受您的字符串并返回正确类型的对象。创建通用接口,并为要爬网的类型进行一些实现:

public interface Parser<T> {

    T parse(String value);

}
现在,回到CSV文件可以有多种类型的问题上,只需稍微改进一下您的阅读器。您所需要的只是一个解析器列表(每列一个),而不是一个解析所有列的解析器


希望这有帮助:-)

如果你想做真正的工作,我建议你忘记这一点,使用它

如果您正在试验:我会将CsvReader设置为一个抽象类:

public abstract class  CsvReader<T> {
...
    // This is what you use in the rest of CsvReader
    // to create your objects from the strings in the CSV
    protected abstract T parse(String s);
...
}
公共抽象类CsvReader{
...
//这是您在CsvReader的其余部分中使用的内容
//从CSV中的字符串创建对象的步骤
受保护的抽象T解析(字符串s);
...
}
它将被用作:

CsvReader<Double> = new CsvReader<Double>() {
    @Override protected Double parse(String s) {
        return Double.valueOf(s);
    }
};
...
CsvReader=new CsvReader(){
@重写受保护的双解析(字符串s){
返回两倍。值为;
}
};
...
不完美,但合理



编辑:事实证明,你可以随心所欲,尽管它看起来有点粗俗。看见它基本上包括CsvReader中的Super-Type-Tokens链接中显示的逻辑,以使与元素类相对应的类对象可用。

创建一个正确的CVS读取器可能比您想象的更困难。例如,在您的代码示例中,它在以下情况下无法正常工作

“微软公司”,1,2,3

不是4个字段,而是5个基于

StringTokenizer st = new StringTokenizer(line,",");
我的建议是,使用第三方库实现。比如说


我在我的一个应用程序中使用它,我的应用程序已经运行了3年。到目前为止还不错。

我需要读取存储在CSV文件单元格中的字符串的简单列表,然后开始搜索Java解决方案。我发现大多数开源CSV阅读器对于我来说都是不必要的复杂。(有关全面审查,请参阅)。 最后我发现MKYong的代码非常有效。我必须根据我的目的修改它,以读取整个CSV或TSV文件,并将其作为列表列表返回。内部列表中的每个元素表示CSV的一个单元格。代码以及MKYong的信用证可在以下网址找到:

+1对于我不知道的java.util.Scanner类,需要它近9000次。是的。至少我会去掉
StringTokenizer
而改用
String.split()
。你们的意思是我应该使用Scanner来实现将文本数据分解并放入ArrayList的代码吗?另外,出于好奇,String.split()相对于StringTokenizer的优势是什么?gpeche,谢谢你的贡献顺便说一句——非常有趣link@Jonah看见
public class StringParser implements Parser<String> {

    public String parse(String value) {
        return value;
    }

}
public CSVReader<T> {

    Parser<T> parser;

    List<T> getValues() {
        // ...
    }

}
public abstract class  CsvReader<T> {
...
    // This is what you use in the rest of CsvReader
    // to create your objects from the strings in the CSV
    protected abstract T parse(String s);
...
}
CsvReader<Double> = new CsvReader<Double>() {
    @Override protected Double parse(String s) {
        return Double.valueOf(s);
    }
};
...
StringTokenizer st = new StringTokenizer(line,",");