Closed SirError closed 7 years ago
Hi again. I was playing around with the code, and got some ideas. Maybe it might help you. Tell me what you think.
I made this scratch.
So we could have a method like this:
public Map<String, Object> nextRecordField() {
if (this.closed) {
throw new IllegalArgumentException("this DBFReader is closed");
}
Map<String, Object> recordObjects = new LinkedHashMap<>();
try {
boolean isDeleted = false;
do {
if (isDeleted && !showDeletedRows) {
skip(this.header.recordLength - 1);
}
int t_byte = this.dataInputStream.readByte();
if (t_byte == END_OF_DATA) {
return null;
}
isDeleted = t_byte == '*';
} while (isDeleted && !showDeletedRows);
if (showDeletedRows) {
recordObjects.put("deleted", isDeleted);
}
for (int i = 0; i < this.header.fieldArray.length; i++) {
DBFField field = this.header.fieldArray[i];
Object o = getFieldValue(field);
if (field.isSystem()) {
if (field.getType() == DBFDataType.NULL_FLAGS) {
if (o instanceof BitSet) {
BitSet nullFlags = (BitSet) o;
int currentIndex = -1;
for (int j = 0; j < this.header.fieldArray.length; j++) {
DBFField field1 = this.header.fieldArray[j];
if (field1.isNullable()) {
currentIndex++;
if (nullFlags.get(currentIndex)) {
recordObjects.put(field1.getName(), null);
}
}
if (field1.getType() == DBFDataType.VARBINARY || field1.getType() == DBFDataType.VARCHAR) {
currentIndex++;
if (recordObjects.get(i) instanceof byte[]) {
byte[] data = (byte[]) recordObjects.get(j);
int size = field1.getLength();
if (!nullFlags.get(currentIndex)) {
// Data is not full
size = data[data.length - 1];
}
byte[] newData = new byte[size];
System.arraycopy(data, 0, newData, 0, size);
Object o1 = newData;
if (field1.getType() == DBFDataType.VARCHAR) {
o1 = new String(newData, getCharset());
}
recordObjects.put(field1.getName(), o1);
}
}
}
}
}
} else {
recordObjects.put(field.getName(), o);
}
}
} catch (EOFException e) {
return null;
} catch (IOException e) {
throw new DBFException(e.getMessage(), e);
}
return recordObjects;
}
this way we return a map, and we can easily get the field using the key record.get("myField");
And to not break the actual api, the method nextRecord could call this one and then convert the return into an array, something like:
public Object[] nextRecord() {
return nextRecordField().entrySet().stream().map(Entry::getValue).toArray();
}
so, what do you think?
It'd be great if instead of an Array of Objects the nextRecord() could return an Object with more info about the collumns. So we could get the columns with something like "row.getString("CollumnName")".