/*
DBFHeader
Class for reading the metadata assuming that the given
InputStream carries DBF data.
This file is part of JavaDBF packege.
Author: anil@linuxense.com
License: LGPL (http://www.gnu.org/copyleft/lesser.html)
$Id$
*/
package whitebox.geospatialfiles.shapefile.attributes;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Vector;
import static whitebox.geospatialfiles.shapefile.attributes.DBFHeader.SIG_DBASE_III;
class DBFHeader {
static final byte SIG_DBASE_III = (byte) 0x03;
/* DBF structure start here */
byte signature; /* 0 */
byte year; /* 1 */
byte month; /* 2 */
byte day; /* 3 */
int numberOfRecords; /* 4-7 */
short headerLength; /* 8-9 */
short recordLength; /* 10-11 */
short reserv1; /* 12-13 */
byte incompleteTransaction; /* 14 */
byte encryptionFlag; /* 15 */
int freeRecordThread; /* 16-19 */
int reserv2; /* 20-23 */
int reserv3; /* 24-27 */
byte mdxFlag; /* 28 */
byte languageDriver; /* 29 */
short reserv4; /* 30-31 */
DBFField[] fieldArray; /* each 32 bytes */
byte terminator1; /* n+1 */
//byte[] databaseContainer; /* 263 bytes */
/* DBF structure ends here */
DBFHeader() {
this.signature = SIG_DBASE_III;
this.terminator1 = 0x0D;
}
void read(DataInput dataInput) throws IOException {
signature = dataInput.readByte(); /* 0 */
year = dataInput.readByte(); /* 1 */
month = dataInput.readByte(); /* 2 */
day = dataInput.readByte(); /* 3 */
numberOfRecords = Utils.readLittleEndianInt(dataInput); /* 4-7 */
headerLength = Utils.readLittleEndianShort(dataInput); /* 8-9 */
recordLength = Utils.readLittleEndianShort(dataInput); /* 10-11 */
reserv1 = Utils.readLittleEndianShort(dataInput); /* 12-13 */
incompleteTransaction = dataInput.readByte(); /* 14 */
encryptionFlag = dataInput.readByte(); /* 15 */
freeRecordThread = Utils.readLittleEndianInt(dataInput); /* 16-19 */
reserv2 = dataInput.readInt(); /* 20-23 */
reserv3 = dataInput.readInt(); /* 24-27 */
mdxFlag = dataInput.readByte(); /* 28 */
languageDriver = dataInput.readByte(); /* 29 */
reserv4 = Utils.readLittleEndianShort(dataInput); /* 30-31 */
Vector v_fields = new Vector();
DBFField field = DBFField.createField(dataInput); /* 32 each */
while (field != null) {
v_fields.addElement(field);
field = DBFField.createField(dataInput);
}
fieldArray = new DBFField[v_fields.size()];
for (int i = 0; i < fieldArray.length; i++) {
fieldArray[ i] = (DBFField) v_fields.elementAt(i);
}
//System.out.println( "Number of fields: " + fieldArray.length);
}
void write(DataOutput dataOutput) throws IOException {
dataOutput.writeByte(signature); /* 0 */
GregorianCalendar calendar = new GregorianCalendar();
year = (byte) (calendar.get(Calendar.YEAR) - 1900);
month = (byte) (calendar.get(Calendar.MONTH) + 1);
day = (byte) (calendar.get(Calendar.DAY_OF_MONTH));
dataOutput.writeByte(year); /* 1 */
dataOutput.writeByte(month); /* 2 */
dataOutput.writeByte(day); /* 3 */
numberOfRecords = Utils.littleEndian(numberOfRecords);
dataOutput.writeInt(numberOfRecords); /* 4-7 */
headerLength = findHeaderLength();
dataOutput.writeShort(Utils.littleEndian(headerLength)); /* 8-9 */
recordLength = findRecordLength();
dataOutput.writeShort(Utils.littleEndian(recordLength)); /* 10-11 */
dataOutput.writeShort(Utils.littleEndian(reserv1)); /* 12-13 */
dataOutput.writeByte(incompleteTransaction); /* 14 */
dataOutput.writeByte(encryptionFlag); /* 15 */
dataOutput.writeInt(Utils.littleEndian(freeRecordThread));/* 16-19 */
dataOutput.writeInt(Utils.littleEndian(reserv2)); /* 20-23 */
dataOutput.writeInt(Utils.littleEndian(reserv3)); /* 24-27 */
dataOutput.writeByte(mdxFlag); /* 28 */
dataOutput.writeByte(languageDriver); /* 29 */
dataOutput.writeShort(Utils.littleEndian(reserv4)); /* 30-31 */
for (int i = 0; i < fieldArray.length; i++) {
fieldArray[i].write(dataOutput);
}
dataOutput.writeByte(terminator1); /* n+1 */
}
private short findHeaderLength() {
return (short) (1
+ 3
+ 4
+ 2
+ 2
+ 2
+ 1
+ 1
+ 4
+ 4
+ 4
+ 1
+ 1
+ 2
+ (32 * fieldArray.length)
+ 1);
}
private short findRecordLength() {
int recordLength = 0;
for (int i = 0; i < fieldArray.length; i++) {
recordLength += fieldArray[i].getFieldLength();
}
return (short) (recordLength + 1);
}
}