
consulting.omnia.util.file.FlatFileDataReader Maven / Gradle / Ivy
The newest version!
package consulting.omnia.util.file;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.text.ParseException;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import consulting.omnia.util.cast.CastUtil;
import consulting.omnia.util.converter.Converter;
import consulting.omnia.util.converter.annotation.DataConverter;
import consulting.omnia.util.file.annotation.FixedSizeField;
import consulting.omnia.util.file.record.RecordType;
import consulting.omnia.util.format.StringUtil;
import consulting.omnia.util.reflection.ReflectionUtil;
public class FlatFileDataReader {
private static final FlatFileDataReader INSTANCE = new FlatFileDataReader();
private InputStream is;
private Integer fileSizeInBytes;
private Integer totalRecords;
private Integer remainder;
private LineFeedType lineFeedType;
private FlatFileDataReader() {
}
public static FlatFileDataReader getInstance() {
return INSTANCE;
}
public void prepare(final InputStream is, final Integer recordSize) throws IOException {
this.is = is;
this.fileSizeInBytes = is.available();
this.totalRecords = fileSizeInBytes / recordSize;
this.remainder = fileSizeInBytes % recordSize;
this.lineFeedType = inferLineFeedType(totalRecords, remainder);
}
public List readRecords(final Class clazz, final Comparator comparator, final RecordType recordType) throws Exception {
switch(recordType) {
case HEADER:
case TRAILLER:
final T record = readRecord(is, clazz, comparator);
lineFeed(is, lineFeedType);
return Collections.singletonList(record);
case DETAIL_ONLY:
return readDetailRecords(clazz, comparator, totalRecords);
case DETAIL_HEADER:
case DETAIL_TRAILLER:
return readDetailRecords(clazz, comparator, totalRecords - 1);
case DETAIL:
return readDetailRecords(clazz, comparator, totalRecords - 2);
default:
throw new UnsupportedOperationException("Unknow record type: [" + recordType + "]");
}
}
private List readDetailRecords(final Class clazz, final Comparator comparator, final Integer recordsToRead) throws Exception {
final List result = new LinkedList();
for(int recordIndex = 0; recordIndex < recordsToRead; recordIndex++) {
final T record = readRecord(is, clazz, comparator);
lineFeed(is, lineFeedType);
result.add(record);
}
return result;
}
private LineFeedType inferLineFeedType(final Integer totalRecords, final Integer remainder) {
final int _remainder = remainder % totalRecords;
int size = 0;
if(_remainder == 0) {
size = remainder / totalRecords;
} else {
size = remainder / (totalRecords - 1);
}
switch(size) {
case 0:
return null;
case 1:
return LineFeedType.UNIX_LIKE;
case 2:
return LineFeedType.WINDOWS_LIKE;
default:
throw new IllegalArgumentException("I don't know any line feed with a such size: [" + size + "]");
}
}
private void lineFeed(final InputStream is, final LineFeedType lineFeedType) throws IOException {
if(lineFeedType == null) {
return;
}
switch (lineFeedType) {
case UNIX_LIKE:
readLineFeedByte(is);
break;
case WINDOWS_LIKE:
readLineFeedByte(is);
readLineFeedByte(is);
break;
default:
throw new IllegalArgumentException("Unkown line feed type: [" + lineFeedType + "]");
}
}
private void readLineFeedByte(final InputStream is) throws IOException {
is.read();
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private T readRecord(final InputStream is, final Class clazz, final Comparator comparator) throws Exception {
final T record = clazz.newInstance();
for (final Field field : ReflectionUtil.listAllFields(record, comparator)) {
if(field.isAnnotationPresent(FixedSizeField.class)) {
final FixedSizeField annotation = field.getAnnotation(FixedSizeField.class);
Object value = read(is, annotation.pos(), annotation.length(), field.getType());
if(field.isAnnotationPresent(DataConverter.class)) {
final DataConverter dataConverter = field.getAnnotation(DataConverter.class);
final Class> converterClass = dataConverter.converter();
final Object converter = converterClass.newInstance();
value = ((Converter) converter).parse(value);
}
if(Modifier.isFinal(field.getModifiers())) {
continue;
}
field.setAccessible(true);
field.set(record, value);
}
}
return record;
}
private Object read(final InputStream is, final int pos, final int size, final Class> clazz) throws IOException, ParseException {
byte[] buffer = new byte[size];
is.read(buffer, 0, size);
final String value = new String(buffer).trim();
if(StringUtil.isEmpty(value)) {
return null;
}
return CastUtil.castAs(value, clazz);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy