Как записать List<String> в CSV-файл и прочитать его обратно, используя supercsv
Я использую supercsv CsvBeanWriter для записи значений в CSV-файл.
образец класса:
public class Employee {
private String name;
private int empId;
List<String> phoneNumbers;
}
Вывод, который я получаю:
name,empId,phoneNumbers
vijay,1,"[123, 456]"
Обратите внимание, как List<String> phoneNumbers
выписан в []
Мой вопрос заключается в том, как мне прочитать его обратно в класс Employee (bean), используя supercsv.
Я пытался с помощью CsvBeanReader
& CsvDozerBeanReader
но не умеет читать List<String>
,
Получаю незаконное исключение. Буду благодарен за любые указатели!
Полный код:
public class DozerBeanReader {
public static void main(String [] args){
ICsvDozerBeanReader beanReader = null;
try {
beanReader = new CsvDozerBeanReader(new FileReader("Employee.csv"),
CsvPreference.STANDARD_PREFERENCE);
String [] header = beanReader.getHeader(true); // ignore the header
Class<?> [] hintTypes = {String.class, Integer.class, List.class};
beanReader.configureBeanMapping(Employee.class, header, hintTypes);
Employee readEmp1 = beanReader.read(Employee.class);
readEmp1.toString();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
1 ответ
Вы полагаетесь на то, что ваш List
телефонных номеров записывается в виде одного столбца CSV с использованием списка toString()
формат, например [123, 456]
,
Вы получите исключение примерно так:
org.dozer.MappingException: Illegal object type
for the method 'setPhoneNumbers'.
Expected types:
java.util.List
Actual types:
java.lang.String
потому что Dozer не знает, как преобразовать строку [123, 456]
к List
, Вы можете сделать это, но вам нужно написать процессор ячейки, чтобы преобразовать эту строку обратно в List
, Если ваши телефонные номера являются чисто номерами, которые не должны быть слишком жесткими, но если ваши телефонные номера имеют запятые, то все будет грязно!
Я бы порекомендовал записать каждый номер телефона в виде отдельной колонки - это значительно облегчает задачу (для всех, кто читает ваш файл, включая вас!).
Все, что вам нужно сделать, это использовать CsvDozerBeanReader и CsvDozerBeanWriter с индексированным отображением.
Вот пример - ключевой частью является индексированное отображение:
String[] fieldMapping = new String[] { "name",
"empId", "phoneNumbers[0]", "phoneNumbers[1]" };
- Я определил 2 столбца телефонных номеров - если ваш список будет иметь больше, то просто добавьте больше столбцов
- Я мог бы использовать fieldMapping для заголовка, но решил использовать более читаемый пользовательский заголовок
- Вам не нужны подсказки, как у вас в вопросе
- Я использовал StringReader/StringWriter только для упрощения примера
Пример:
// create employee to write/read
Employee employee = new Employee();
employee.setEmpId(1234);
employee.setName("Vijay");
employee.setPhoneNumbers(Arrays.asList("123", "456"));
// the CSV header
String[] header = new String[] { "name",
"empId", "phoneNumber1", "phoneNumber2" };
// the field mapping
String[] fieldMapping = new String[] { "name",
"empId", "phoneNumbers[0]", "phoneNumbers[1]" };
// write the employee
StringWriter out = new StringWriter();
ICsvDozerBeanWriter writer =
new CsvDozerBeanWriter(out,
CsvPreference.STANDARD_PREFERENCE);
writer.configureBeanMapping(Employee.class, fieldMapping);
writer.writeHeader(header);
writer.write(employee);
writer.flush();
// read the employee
ICsvDozerBeanReader reader =
new CsvDozerBeanReader(new StringReader(out.toString()),
CsvPreference.STANDARD_PREFERENCE);
reader.configureBeanMapping(Employee.class, fieldMapping);
reader.getHeader(true); // ignore header
Employee e = reader.read(Employee.class);
System.out.println(e);
Предполагая, что вы написали toString()
метод, это должно напечатать
Employee [name=Vijay, empId=1234, phoneNumbers=[123, 456]]