Итак, приступим к написанию reader-а:
/** * @author vie * * TSVReader.java * Class for read tab separated values files */ public class TSVReader<T> { private final String filePath; public TSVReader(String filePath) { this.filePath = filePath; } /** * This method reads tab separated values file * into object of the arbitrary class * * @param clazz type of transmitted class * @return List * @throws com.site.tsv.exceptions.TSVException */ public List<T> read(Class<T> clazz) throws TSVException { List<T> result = new LinkedList<T>(); try { BufferedReader bReader = new BufferedReader(new FileReader(filePath)); String line; //recieving all lines int i = 1; while ((line = bReader.readLine()) != null) { //recieving all line members String datavalue[] = line.split("\t"); //create instance of line entity Constructor constructor = clazz.getConstructor(null); Object somethingInstance = constructor.newInstance(null); //parsing line entity members Field[] fields = clazz.getDeclaredFields(); //recieve map of line entity member types Map<Integer, Class<?>> mapFields = defineFields(clazz); //for each line entity field if (fields != null && datavalue != null && fields.length == datavalue.length) { for (int j = 0; j < fields.length; j++) { //for each line entity field String s = fields[j].getName(); s = s.substring(0, 1).toUpperCase() + s.substring(1, s.length()); //exec line entity setter methods Method method = clazz.getMethod("set" + s, mapFields.get(j)); method.invoke(somethingInstance, getDeterminatedValue(datavalue[j], fields[j].getType())); } } else if (fields != null && datavalue != null && fields.length != datavalue.length) { throw new TSVInvalidFileException("Count of formatted file fields on line " + i + " not equal count of entity fields"); } i++; result.add((T) somethingInstance); } bReader.close(); } catch (FileNotFoundException e) { throw new TSVException(e); } catch (IOException e) { throw new TSVException(e); } catch (ParseException e) { throw new TSVInvalidFileException(e); } catch (NumberFormatException e) { throw new TSVInvalidFileException(e); } catch (NoSuchMethodException e) { //reflect throw new TSVException(e); } catch (InstantiationException e) { throw new TSVException(e); } catch (IllegalAccessException e) { throw new TSVException(e); } catch (InvocationTargetException e) { throw new TSVException(e); } return result; } /** * Returns field names and types * * @param clazz type of transmitted class * @return Map<string,integer>. * @throws com.site.tsv.exceptions.TSVIncorrectAnnotatedFieldsException */ private Map<Integer, Class<?>> defineFields(Class<?> clazz) throws TSVIncorrectAnnotatedFieldsException { Map<Integer, Class<?>> map = new HashMap<Integer, Class<?>>(); Field[] fields = clazz.getDeclaredFields(); int i = 0; for (Field field : fields) { if (field.isAnnotationPresent(TSVInteger.class)) { map.put(i++, Integer.class); } else if (field.isAnnotationPresent(TSVDouble.class)) { map.put(i++, Double.class); } else if (field.isAnnotationPresent(TSVString.class)) { map.put(i++, String.class); } else if (field.isAnnotationPresent(TSVDate.class)) { map.put(i++, Date.class); } } if (fields.length == 0 || fields.length != map.size()) { throw new TSVIncorrectAnnotatedFieldsException("Some field not annotated or count of fields = 0!"); } return map; } /** * Returns converted to the native type field * * @param original value of obtained field * @param needType type of transmitted class * @return Object * @throws java.text.ParseException */ private Object getDeterminatedValue(String original, Class<?> needType) throws ParseException { if (needType.getName().equals("java.lang.Integer")) { return Integer.parseInt(original); } else if (needType.getName().equals("java.lang.Double")) { return Double.parseDouble(original); } else if (needType.getName().equals("java.lang.String")) { return original; } else if (needType.getName().equals("java.util.Date")) { SimpleDateFormat formatter = new SimpleDateFormat("dd.MM.yyyy"); return formatter.parse(original); } else { return null; } } }В классе я использовал generics, чтобы проверять заданного типы entity на этапе компиляции. В преобразовании строк с различными типами данных в entity объект мне помог reflection. Для разбора с его помощью entity, написаны приведенные ниже аннотации. Также я создал несколько исключений, чтобы в при выпадении ошибок можно было быстро понять что свалилось, будь то reflection, IO или преобразование чисел и дат.
теперь Writer:
/** * @author vie * * TSVWriter.java * Class for write tab separated values files */ public class TSVWriter<T> { private final static String tab = "\t"; private final String filePath; public TSVWriter(String filePath) { this.filePath = filePath; } /** * This method writes tab separated values file * from entity object * * @param list list of line entity objects * @param clazz type of transmitted class * @throws com.site.tsv.exceptions.TSVException */ public void write(List<T> list, Class<T> clazz) throws TSVException { try { BufferedWriter bufferWriter = new BufferedWriter(new FileWriter(filePath)); //getting all line object fields Field[] fields = clazz.getDeclaredFields(); //for each line if (fields != null) { for (T lineObject: list) { StringBuilder line = new StringBuilder(); //for each line entity field for (Field field : fields) { String s = field.getName(); s = s.substring(0, 1).toUpperCase() + s.substring(1, s.length()); //exec line entity setter methods Method method = clazz.getMethod("get" + s); String val = method.invoke(lineObject) + ""; line.append(val).append(tab); } bufferWriter.write(line.substring(0, line.length() - 1)); bufferWriter.newLine(); } } bufferWriter.close(); } catch (FileNotFoundException e) { throw new TSVException(e); } catch (IOException e) { throw new TSVException(e); } catch (NoSuchMethodException e) { throw new TSVException(e); } catch (IllegalAccessException e) { throw new TSVException(e); } catch (InvocationTargetException e) { throw new TSVException(e); } } }
Аннотации:
/** * @author vie */ @Target(value = ElementType.FIELD) @Retention(value = RetentionPolicy.RUNTIME) public @interface TSVInteger { } /** * @author vie */ @Target(value = ElementType.FIELD) @Retention(value = RetentionPolicy.RUNTIME) public @interface TSVDouble { } /** * @author vie */ @Target(value = ElementType.FIELD) @Retention(value = RetentionPolicy.RUNTIME) public @interface TSVString { } /** * @author vie */ @Target(value = ElementType.FIELD) @Retention(value = RetentionPolicy.RUNTIME) public @interface TSVDate { }
Исключения:
/** * @author vie */ public class TSVException extends Exception { public TSVException() { super(); } public TSVException(String message) { super(message); } public TSVException(String message, Throwable cause) { super(message, cause); } public TSVException(Throwable cause) { super(cause); } } /** * @author vie */ public class TSVInvalidFileException extends TSVException { public TSVInvalidFileException() { super(); } public TSVInvalidFileException(String message) { super(message); } public TSVInvalidFileException(String message, Throwable cause) { super(message, cause); } public TSVInvalidFileException(Throwable cause) { super(cause); } } /** * @author vie */ public class TSVIncorrectAnnotatedFieldsException extends TSVException { public TSVIncorrectAnnotatedFieldsException() { super(); } public TSVIncorrectAnnotatedFieldsException(String message) { super(message); } public TSVIncorrectAnnotatedFieldsException(String message, Throwable cause) { super(message, cause); } public TSVIncorrectAnnotatedFieldsException(Throwable cause) { super(cause); } }
Все, теперь можно попробовать загрузить и записать в другой файл. Для этого создадим entity, аналогичный структуре файла:
test1 55 01.01.2010 rw test2 daswqrg 56 31.01.2011 comment1 test3 dds 57 30.11.2011 comment32
entity:
/** * @author vie */ public class TestLineEntity { @TSVString protected String value; @TSVInteger protected Integer id; @TSVDate protected Date date; @TSVString protected String comment; public String getValue() { return value; } public void setValue(String value) { this.value = value; } /*other getters and setters*/ }
сам код считывания и записи данных:
TSVReader<TestLineEntity> tsvReader = new TSVReader<TestLineEntity>("test.tsv"); List<TestLineEntity> test = tsvReader.read(TestLineEntity.class); TSVWriter<TestLineEntity> tsvWriter = new TSVWriter<TestLineEntity>("new_test.tsv"); tsvWriter.write(forum, TestLineEntity.class);
Комментариев нет:
Отправить комментарий