uniVocity - 按位置转换为List

时间:2017-02-23 20:55:52

标签: java csv univocity

我正在尝试从csv文件中的特定位置创建一个List,而不是括号。

class Person {//
@Parsed
private String name;
@??
private Address address;
@Convert(conversionClass = Emails2.class, args = { "," , "5,6" })
@Parsed
private List<String> emails;
}

csv格式:

name,email1,email2,email3,street,number,neighborhood
Maria,ma@gmail.com,ma@hotmail.com,,Regent Street,12,downtown
Ana,ana@gmail.com,a@hotmail.com,,Bird Street,,east side

我需要阅读csv文件并创建一个电子邮件列表和一个Address对象。 我试图使用@Convert,

public class Emails2 implements Conversion<String, Set<String>> {

    private final String separator;
    private final Set<String> positions;

    public Emails2(String... args) {
        String separator = ",";
        Set<String> positions = null;

        if (args.length == 1) {
            separator = args[0];
        }

        if (args.length == 2) {
            positions = new HashSet<String>();
            String[] posi = args[1].split(",");
            for (String string : posi) {
                positions.add(string);
            }
        }
        this.separator = separator;
        this.positions = positions;
    }

    public Emails2(String separator, Set<String> positions) {
        this.separator = separator;
        this.positions = positions;
    }
//this method is not called, I don't know why
    public Set<String> execute(String input) { //I would like add the list and Address object inside this method to get it done in beanProcessed(...)
        if (input == null) {
            return Collections.emptySet();
        }

        Set<String> out = new TreeSet<String>();
        for (String token : input.split(separator)) {
            for (String word : token.trim().split("\\s")) {
                out.add(word.trim());
            }
        }
        return out;
    }

    public String revert(Set<String> input) {
        return revert(input);
    }

}

我是怎么做的

    public static void main(String[] args) {

            BeanProcessor<Person> rowProcessor = new BeanProcessor<Person>(Person.class) {
                @Override
                public void beanProcessed(Person c, ParsingContext context) {
                    System.out.println(c.getName());

                    String[] positions = context.currentParsedContent().split(","); 
                    System.out.println(positions[5]);
//I'm using fixed position here, I'd like get the position from @Convert or another way by configuration
                    System.out.println(positions[6]);
                    List<String> list = new ArrayList<>();
                    list.add(positions[5]);
                    list.add(positions[6]);
                    c.setEmails(list);
                }

            };

            CsvParserSettings parserSettings = new CsvParserSettings();
            parserSettings.setRowProcessor(rowProcessor);
            parserSettings.setHeaderExtractionEnabled(true);
            CsvParser parser2 = new CsvParser(parserSettings);
            parser2.parse(getReader("/var/lib/cob/test2.csv"));

        }

2 个答案:

答案 0 :(得分:0)

您正尝试通过自定义转化将多列(email1email2email3)的值分配到单个属性(Person.emails)中,但这是不支持,因为转化的目标是单个字段(或输入列),而不是整行。

此外,由于输入中没有execute标头,因此不会调用自定义转换中的emails方法。使用@Parsed注释注释属性而不提供要匹配的标题名称时,将使用属性名称本身。如果您将属性从emails重命名为email1,则会看到您的转化类将被调用,或者您只是在注释中提供字段名称,如下所示:

@Parsed(field = "email1")
private List<String> emails;

它也会被调用。

我看到你在这里尝试做什么并打开this issue以便为这类要求提供更好的支持。

希望这有帮助。

答案 1 :(得分:0)

我以另一种方式实现了我想要的东西,不像我想的那样,但它有效。我使用了MultiBeanProcessor并创建了虚拟类(我的老板不喜欢)来表示我的csv位置。

我真正的csv有以下标题:

  

EMAIL1,EMAIL2,EMAIL3,dddcel1,dddcel2,dddcel3,dddcel4,dddtel1,dddtel2,dddtel3,名字,文件,v_atu,ofe_cc,ignore1,银行,机构,ignore2,invoiceNumber,contactPhone,地址,街道,邮编,城市,状态

    class Email{
    @Parsed 
    private String email1;
    @Parsed 
    private String email2;
     @Parsed
    private String email3;
    }

class Mobile{
    @Parsed
    private String dddcel1;
    @Parsed
    private String dddcel2;
    @Parsed
    private String dddcel3;
    @Parsed
    private String dddcel4;
}

和MultiBeanProcessor

 MultiBeanProcessor processor = new MultiBeanProcessor(Customer.class, Address.class, Email.class, Mobile.class, Phone.class) {
            private Customer customer;
            private Address address;
            private Email email;
            private Mobile mobile;
            private Phone phone;

            @Override
            public void beanProcessed(Class<?> beanType, Object beanInstance, ParsingContext context) {

                if (beanType == Customer.class) {
                    customer = (Customer) beanInstance;
                    customer.set_id(UUID.randomUUID().toString());
                    customer.setStatus(CustomerStatusType.PENDING);
                    customer.setDiscountValue(customer.getInvoiceValue() - customer.getTotalValue());
                    customer.setToken(UUID.randomUUID().toString());
                    try {
                        customer.setCreated(new java.text.SimpleDateFormat("yyyy-MM-dd")
                                .parse((new java.text.SimpleDateFormat("yyyy-MM-dd").format(new java.util.Date()))));
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }

                    customer.setDomain("???????????");
                    Map<String, String> map = new HashMap<String, String>();
                    map.put("banco", customer.getBank());
                    map.put("agencia", customer.getAgency());
                    customer.setInvoiceDetail(map);

                }

                if (beanType == Address.class) {
                    address = (Address) beanInstance;
                    customer.setAddress(address);
                }

                if (beanType == Email.class) {
                    email = (Email) beanInstance;
                    customer.setEmails(Arrays.asList(email.getEmail1(), email.getEmail2(), email.getEmail3()));
                }

                if (beanType == Mobile.class) {
                    mobile = (Mobile) beanInstance;
                    customer.setMobiles(Arrays.asList(mobile.getDddcel1(), mobile.getDddcel2(), mobile.getDddcel3(), mobile.getDddcel4()));

                }

                if (beanType == Phone.class) {
                    phone = (Phone) beanInstance;
                    customer.setPhones(Arrays.asList(phone.getDddtel1(), phone.getDddtel2(), phone.getDddtel3()));
                }

                if (customer != null && address != null && email != null && mobile != null & phone != null) {
                    System.out.println(customer);//save customer object
                    customer = null;
                    address = null;
                    email = null;
                    phone = null;
                    mobile = null;
                }

            }
        };

我正在测试,我希望它适用于500k行:)