libreria java csv opencsv supercsv

libreria - OpenCSV: cómo asignar las columnas seleccionadas a Java Bean independientemente del orden?



opencsv java (9)

Aquí hay una buena manera de usar OpenCSV para hacer la asignación a POJO genéricamente:

protected <T> List<T> mapToCSV(String csvContent, Class<T> mapToClass) { CsvToBean<T> csvToBean = new CsvToBean<T>(); Map<String, String> columnMapping = new HashMap<>(); Arrays.stream(mapToClass.getDeclaredFields()).forEach(field -> { columnMapping.put(field.getName(), field.getName()); }); HeaderColumnNameTranslateMappingStrategy<T> strategy = new HeaderColumnNameTranslateMappingStrategy<T>(); strategy.setType(mapToClass); strategy.setColumnMapping(columnMapping); CSVReader reader = new CSVReader(new StringReader(csvContent)); return csvToBean.parse(strategy, reader); } public static class MyPojo { private String foo, bar; public void setFoo(String foo) { this.foo = foo; } public void setBar(String bar) { this.bar = bar; } }

Luego de su prueba puede usar:

List<MyPojo> list = mapToCSV(csvContent, MyPojo.class);

Tengo un archivo CSV con las siguientes columnas: id , fname , telephone , lname , address .

Tengo una clase Person con los miembros de datos id , fname y lname . Quiero asignar solo estas columnas al objeto Person desde un archivo CSV y descartar telephone columnas de telephone y address . ¿Cómo puedo hacer esto? La solución debe escalar a medida que se agreguen más columnas en el futuro. Y debería funcionar independientemente de la posición de la columna.

En una solución ideal, el usuario solo especificará columnas para leer y simplemente debería funcionar.


Eche un vistazo a jcsvdao, https://github.com/eric-mckinley/jcsvdao/ , utiliza archivos de mapeo de hibernación y puede manejar las relaciones 1to1 y 1toMany. Es bueno si no posee los archivos csv ya que tiene estrategias de emparejamiento flexibles.


Implementé una solución flexible para abordar este problema. Es muy fácil de usar y el código con el ejemplo está disponible en mi github a continuación:

https://github.com/jsinghfoss/opencsv


Las versiones recientes de OpenCSV anulan el parse(X, Y) del método parse(X, Y) y se reinicia el uso de BeanBuilder, por lo que la respuesta principal está desactualizada.

try { CsvToBeanBuilder<PersonCSV> beanBuilder = new CsvToBeanBuilder<>(new InputStreamReader(new FileInputStream("your.csv"))); beanBuilder.withType(PersonCSV.class); // build methods returns a list of Beans beanBuilder.build().parse().forEach(e -> log.error(e.toString())); } catch (FileNotFoundException e) { log.error(e.getMessage(), e); }

Este método le permite limpiar el código y eliminar MappingStrategy (aún puede usarlo si le gusta el espagueti), de modo que puede anotar su clase CSV de la siguiente manera:

@CsvDate("dd/MM/yyyy hh:mm:ss") @CsvBindByName(column = "Time Born", required = true) private Date birthDate;


No puedo hablar por opencsv, pero esto se puede lograr fácilmente usando Super CSV , que tiene dos readers diferentes que admiten lectura parcial (ignorando columnas), así como la lectura en Javabean. CsvDozerBeanReader es incluso capaz de mapeo profundo y basado en índices , por lo que puede mapear a los campos anidados.

Nosotros (el equipo Super CSV) acabamos de lanzar la versión 2.0.0, que está disponible desde Maven central o SourceForge.

Actualizar

Aquí hay un ejemplo (basado en la prueba en el proyecto GitHub que ha creado), que utiliza Super CSV en lugar de opencsv. Tenga en cuenta que las preferencias de CSV necesitaban el marcador surroundingSpacesNeedQuotes habilitado porque su archivo CSV de ejemplo no es válido (tiene espacios entre los campos, los espacios se consideran parte de los datos en 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(); }


Puede usar HeaderColumnNameTranslateMappingStrategy . Supongamos que su CSV tiene las siguientes columnas: Id , Fname , Telephone , Lname , Address por simplicidad.

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

La asignación de columnas mapeará las columnas con su objeto Person .


Use uniVocity-parsers y uniVocity-parsers con esto. No importa cómo se organicen las columnas en el archivo CSV de entrada, solo se analizarán las que necesita.

Si escribe, las columnas que tiene en clase se escribirán en las columnas correctas, mientras que las otras estarán vacías.

Aquí hay una clase con algunos ejemplos:

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; }

Aquí se muestra cómo obtener una lista de 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();

Divulgación: soy el autor de esta biblioteca. Es de código abierto y gratuito (licencia de Apache V2.0).


la última versión de https://github.com/arnaudroger/SimpleFlatMapper 0.9.4 ahora tiene un CsvMapper. Utiliza el encabezado para coincidir con el nombre de la propiedad o, si no hay un encabezado, puede especificar el nombre de la columna a través del generador. Es compatible con el constructor, setter y campo de inyección. Lea desde InputStream o Reader.

public class MyParser { private final CsvMapper<MyObject> mapper = CsvMapperFactory.newInstance().newMapper(MyObject.class); public void writeAllObjectToLambda(Writer writer, InputStream is) throws IOException { mapper.forEach(is, (o) -> writer.append(o.toString()).append("/n")); } }


uso de ejemplo de jcvsdao

Archivo CSV de usuario de muestra

Username, Email, Registration Date, Age, Premium User Jimmy, [email protected], 04-05-2016, 15, Yes, M Bob, [email protected], 15-01-2012, 32, No, M Alice, [email protected], 22-09-2011, 24, No, F Mike, [email protected], 11-03-2012, 18, Yes, M Helen, [email protected], 02-12-2013, 22, Yes, F Tom, [email protected], 08-11-2015, 45, No, M

Crear un 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>