OpenCSV - How to map selected columns to Java Bean regardless of order?

前端 未结 10 878
终归单人心
终归单人心 2020-11-30 06:38

I have a CSV file with the following columns: id, fname, telephone, lname, address.

I have a P

相关标签:
10条回答
  • 2020-11-30 07:19

    I can't speak for opencsv, but this is easily achievable using Super CSV, which has two different readers that support partial reading (ignoring columns), as well as reading into a Javabean. CsvDozerBeanReader is even capable of deep and index-based mapping, so you can map to nested fields.

    We (the Super CSV team) have just released version 2.0.0, which is available from Maven central or SourceForge.

    Update

    Here's an example (based on the test in the GitHub project you've created), that uses Super CSV instead of opencsv. Note the CSV preferences needed the surroundingSpacesNeedQuotes flag enabled as your example CSV file isn't valid (it has spaces between the fields - spaces are considered part of the data in CSV).

    ICsvBeanReader beanReader = null;
    try {
        beanReader = new CsvBeanReader(
                new InputStreamReader(
                        ClassLoader.getSystemResourceAsStream("test.csv")),
                new CsvPreference.Builder(CsvPreference.STANDARD_PREFERENCE)
                        .surroundingSpacesNeedQuotes(true).build());
    
        List<String> columnsToMap = Arrays.asList("fname", "telephone", "id");
    
        // read the CSV header (and set any unwanted columns to null)
        String[] header = beanReader.getHeader(true);
        for (int i = 0; i < header.length; i++) {
            if (!columnsToMap.contains(header[i])) {
                header[i] = null;
            }
        }
    
        Person person;
        while ((person = beanReader.read(Person.class, header)) != null) {
            System.out.println(person);
        }
    
    } finally {
        beanReader.close();
    }
    
    0 讨论(0)
  • 2020-11-30 07:20

    You can use HeaderColumnNameTranslateMappingStrategy. Lets assume your CSV has the following columns: Id, Fname, Telephone, Lname, Address for the sake of simplicity.

    CsvToBean<Person> csvToBean = new CsvToBean<Person>();
    
    Map<String, String> columnMapping = new HashMap<String, String>();
    columnMapping.put("Id", "id");
    columnMapping.put("Fname", "fname");
    columnMapping.put("Lname", "lname");
    
    HeaderColumnNameTranslateMappingStrategy<Person> strategy = new HeaderColumnNameTranslateMappingStrategy<Person>();
    strategy.setType(Person.class);
    strategy.setColumnMapping(columnMapping);
    
    List<Person> list = null;
    CSVReader reader = new CSVReader(new InputStreamReader(ClassLoader.getSystemResourceAsStream("test.csv")));
    list = csvToBean.parse(strategy, reader);
    

    The columnMapping will map the columns with your Person object.

    0 讨论(0)
  • 2020-11-30 07:21

    Use uniVocity-parsers and be done with it. It doesn't matter how the columns are organized in the input CSV, only the ones you need will be parsed.

    If writing, the columns you have in class will be written to the correct columns, while the others will be empty.

    Here's a class with some examples:

    class TestBean {
    
        // if the value parsed in the quantity column is "?" or "-", it will be replaced by null.
        @NullString(nulls = { "?", "-" })
        // if a value resolves to null, it will be converted to the String "0".
        @Parsed(defaultNullRead = "0")
        private Integer quantity;   // The attribute type defines which conversion will be executed when processing the value.
    
        @Trim
        @LowerCase
        // the value for the comments attribute is in the column at index 4 (0 is the first column, so this means fifth column in the file)
        @Parsed(index = 4)
        private String comments;
    
        // you can also explicitly give the name of a column in the file.
        @Parsed(field = "amount")
        private BigDecimal amount;
    
        @Trim
        @LowerCase
        // values "no", "n" and "null" will be converted to false; values "yes" and "y" will be converted to true
        @BooleanString(falseStrings = { "no", "n", "null" }, trueStrings = { "yes", "y" })
        @Parsed
        private Boolean pending;
    }
    

    Here's how to get a list of TestBean

    BeanListProcessor<TestBean> rowProcessor = new BeanListProcessor<TestBean>(TestBean.class);
    
    CsvParserSettings parserSettings = new CsvParserSettings();
    parserSettings.setRowProcessor(rowProcessor);
    parserSettings.setHeaderExtractionEnabled(true);
    
    CsvParser parser = new CsvParser(parserSettings);
    parser.parse(getReader("/examples/bean_test.csv"));
    
    List<TestBean> beans = rowProcessor.getBeans();
    

    Disclosure: I am the author of this library. It's open-source and free (Apache V2.0 license).

    0 讨论(0)
  • 2020-11-30 07:21

    jcvsdao example usage

    Sample User CSV file

    Username, Email, Registration Date, Age, Premium User
    Jimmy, jim@test.com, 04-05-2016, 15, Yes, M
    Bob, bob@test.com, 15-01-2012, 32, No, M
    Alice, alice@test.com, 22-09-2011, 24, No, F
    Mike, mike@test.com, 11-03-2012, 18, Yes, M
    Helen, helen@test.com, 02-12-2013, 22, Yes, F
    Tom, tom@test.com, 08-11-2015, 45, No, M
    

    Create A CsvDao

    CSVDaoFactory factory = new CSVDaoFactory("/csv-config.xml");
    CSVDao dao = new CSVDao(factory);
    List<UserDetail> users = dao.find(UserDetail.class);
    

    csv-config.xml

    <CSVConfig>
        <mappingFiles fileType="resource">
            <mappingFile>/example01/mapping/UserDetail.csv.xml</mappingFile>
        </mappingFiles>
    </CSVConfig>
    

    UserDetail.csv.xml

    <CSVMapping className="org.jcsvdao.examples.example01.model.UserDetail" csvFile="csv-examples/example01/users.txt" delimiter="," ignoreFirstLine="true">
        <matchAll/>
        <properties>
            <property index="0" property="username" primaryKey="true"/>
            <property index="1" property="email"/>
            <property index="2" property="registrationDate" converter="myDateConverter"/>
            <property index="3" property="age"/>
            <property index="4" property="premiumUser" converter="yesNoConverter"/>
            <property index="5" property="gender" converter="myGenderConverter"/>
        </properties>
        <converters>
            <dateConverter converterName="myDateConverter" format="dd-MM-yyyy"/>
            <booleanConverter converterName="yesNoConverter" positive="Yes" negative="No"/>
            <customConverter converterName="myGenderConverter" converterClass="org.jcsvdao.examples.example01.converter.GenderCustomerConverter"/>
        </converters>
    </CSVMapping>
    
    0 讨论(0)
提交回复
热议问题