代码之家  ›  专栏  ›  技术社区  ›  Jonah

创建通用CsvReader

  •  0
  • Jonah  · 技术社区  · 14 年前

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

    ArrayList<ArrayList<T>>.  
    

    //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)); 
    

    但我甚至不能在一个小时内通过双人舱解决方案。问题是,实际情况是,我需要对具有以下属性的类型“参数化”我的类(在这个词的一般意义上,而不是技术上的java泛型意义上):它有一个接受单个字符串参数的ctor。也就是说,要在双csv文件上创建行ArrayLists,我需要编写:

    StringTokenizer st = new StringTokenizer(line,",");
    ArrayList<Double> curRow = new ArrayList<Double>();
    while (st.hasMoreTokens()) {
     curRow.add(new Double(st.nextToken());
    }
    

    已经过去了双人舱,我可以得到它的字符串

      Constructor ctor = c.getConstructor(new Class[] {String.class});
    

    但这有两个问题。最重要的是,这是一个通用构造函数,它将返回一个类型对象,我不能将其向下转换为Double。第二,我将缺少“类型”检查,因为我要求传入的类必须有一个字符串arg构造函数。

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

    约拿

    4 回复  |  直到 14 年前
        1
  •  7
  •   Vivien Barousse    14 年前

    我不确定一个通用的CSV阅读器会这么简单使用(顺便说一句,创建)。

    无论如何,假设您想创建一个CSV读取器,其中所有列的类型都相同。正如您所说的,您不能参数化接受 String 作为建造师”。Java就是不允许这样。使用反射的解决方案是一个良好的开端。但是如果你的课不考呢 字符串 作为它的一个构造函数中的参数?

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

    public interface Parser<T> {
    
        T parse(String value);
    
    }
    

    public class StringParser implements Parser<String> {
    
        public String parse(String value) {
            return value;
        }
    
    }
    

    然后,你可以 Parser 作为它的参数之一。然后,它可以使用这个解析器来转换每个 转换为Java对象。

    有了这个解决方案,你就摆脱了你使用的不太漂亮的反射。你可以转换成任何类型,你只需要实现一个 .

    public CSVReader<T> {
    
        Parser<T> parser;
    
        List<T> getValues() {
            // ...
        }
    
    }
    

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

    希望有帮助:-)

        2
  •  1
  •   Cheok Yan Cheng    14 年前

    创建 对的 简历阅读器可能比你想象的要难。例如,在您的代码示例中,它在以下情况下无法正常工作。

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

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

    StringTokenizer st = new StringTokenizer(line,",");
    

    我的建议是,使用第三方库实现。例如

    http://opencsv.sourceforge.net/

        3
  •  1
  •   BalusC    12 年前

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

    如果你在试验:我会把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<Double> = new CsvReader<Double>() {
        @Override protected Double parse(String s) {
            return Double.valueOf(s);
        }
    };
    ...
    


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

        4
  •  0
  •   AgilePro    4 年前

    我需要读取存储在CSV文件单元格中的字符串的简单列表,然后开始搜索Java解决方案。我发现大多数开源CSV阅读器对于我来说都是不必要的复杂。(见 https://agiletribe.purplehillsbooks.com/2012/11/23/the-only-class-you-need-for-csv-files/ https://github.com/ramanraja/CsvReader