📄 dbasefileheader.java
字号:
tempLength += tempFieldDescriptors[j].fieldLength;
// only increment j on non-matching fields
j++;
} else {
retCol = i;
}
}
// set the new fields.
fields = tempFieldDescriptors;
headerLength = 33 + 32 * fields.length;
recordLength = tempLength;
return retCol;
}
// Retrieve the length of the field at the given index
/**
* Returns the field length in bytes.
*
* @param inIndex
* The field index.
* @return The length in bytes.
*/
public int getFieldLength(int inIndex) {
return fields[inIndex].fieldLength;
}
// Retrieve the location of the decimal point within the field.
/**
* Get the decimal count of this field.
*
* @param inIndex
* The field index.
* @return The decimal count.
*/
public int getFieldDecimalCount(int inIndex) {
return fields[inIndex].decimalCount;
}
// Retrieve the Name of the field at the given index
/**
* Get the field name.
*
* @param inIndex
* The field index.
* @return The name of the field.
*/
public String getFieldName(int inIndex) {
return fields[inIndex].fieldName;
}
// Retrieve the type of field at the given index
/**
* Get the character class of the field.
*
* @param inIndex
* The field index.
* @return The dbase character representing this field.
*/
public char getFieldType(int inIndex) {
return fields[inIndex].fieldType;
}
/**
* Get the date this file was last updated.
*
* @return The Date last modified.
*/
public Date getLastUpdateDate() {
return date;
}
/**
* Return the number of fields in the records.
*
* @return The number of fields in this table.
*/
public int getNumFields() {
return fields.length;
}
/**
* Return the number of records in the file
*
* @return The number of records in this table.
*/
public int getNumRecords() {
return recordCnt;
}
/**
* Get the length of the records in bytes.
*
* @return The number of bytes per record.
*/
public int getRecordLength() {
return recordLength;
}
/**
* Get the length of the header
*
* @return The length of the header in bytes.
*/
public int getHeaderLength() {
return headerLength;
}
/**
* Read the header data from the DBF file.
*
* @param channel
* A readable byte channel. If you have an InputStream you
* need to use, you can call
* java.nio.Channels.getChannel(InputStream in).
* @throws IOException
* If errors occur while reading.
*/
public void readHeader(ReadableByteChannel channel) throws IOException {
// we'll read in chunks of 1K
ByteBuffer in = ByteBuffer.allocateDirect(1024);
// do this or GO CRAZY
// ByteBuffers come preset to BIG_ENDIAN !
in.order(ByteOrder.LITTLE_ENDIAN);
// only want to read first 10 bytes...
in.limit(10);
read(in, channel);
in.position(0);
// type of file.
byte magic = in.get();
if (magic != MAGIC) {
throw new IOException("Unsupported DBF file Type "
+ Integer.toHexString(magic));
}
// parse the update date information.
int tempUpdateYear = in.get();
int tempUpdateMonth = in.get();
int tempUpdateDay = in.get();
// ouch Y2K uncompliant
if (tempUpdateYear > 90) {
tempUpdateYear = tempUpdateYear + 1900;
} else {
tempUpdateYear = tempUpdateYear + 2000;
}
Calendar c = Calendar.getInstance();
c.set(Calendar.YEAR, tempUpdateYear);
c.set(Calendar.MONTH, tempUpdateMonth - 1);
c.set(Calendar.DATE, tempUpdateDay);
date = c.getTime();
// read the number of records.
recordCnt = in.getInt();
// read the length of the header structure.
// ahhh.. unsigned little-endian shorts
// mask out the byte and or it with shifted 2nd byte
headerLength = (in.get() & 0xff) | ((in.get() & 0xff) << 8);
// if the header is bigger than our 1K, reallocate
if (headerLength > in.capacity()) {
NIOUtilities.clean(in);
in = ByteBuffer.allocateDirect(headerLength - 10);
}
in.limit(headerLength - 10);
in.position(0);
read(in, channel);
in.position(0);
// read the length of a record
// ahhh.. unsigned little-endian shorts
recordLength = (in.get() & 0xff) | ((in.get() & 0xff) << 8);
// skip / skip thesreserved bytes in the header.
in.position(in.position() + 20);
// calculate the number of Fields in the header
fieldCnt = (headerLength - FILE_DESCRIPTOR_SIZE - 1)
/ FILE_DESCRIPTOR_SIZE;
// read all of the header records
List lfields = new ArrayList();
for (int i = 0; i < fieldCnt; i++) {
DbaseField field = new DbaseField();
// read the field name
byte[] buffer = new byte[11];
in.get(buffer);
String name = new String(buffer);
int nullPoint = name.indexOf(0);
if (nullPoint != -1) {
name = name.substring(0, nullPoint);
}
field.fieldName = name.trim();
// read the field type
field.fieldType = (char) in.get();
// read the field data address, offset from the start of the record.
field.fieldDataAddress = in.getInt();
// read the field length in bytes
int length = (int) in.get();
if (length < 0) {
length = length + 256;
}
field.fieldLength = length;
if (length > largestFieldSize) {
largestFieldSize = length;
}
// read the field decimal count in bytes
field.decimalCount = (int) in.get();
// rreservedvededved bytes.
// in.skipBytes(14);
in.position(in.position() + 14);
// some broken shapefiles have 0-length attributes. The reference
// implementation
// (ArcExplorer 2.0, built with MapObjects) just ignores them.
if (field.fieldLength > 0) {
lfields.add(field);
}
}
// Last byte is a marker for the end of the field definitions.
// in.skipBytes(1);
in.position(in.position() + 1);
NIOUtilities.clean(in);
fields = new DbaseField[lfields.size()];
fields = (DbaseField[]) lfields.toArray(fields);
}
/**
* Get the largest field size of this table.
*
* @return The largt field size iiin bytes.
*/
public int getLargestFieldSize() {
return largestFieldSize;
}
/**
* Set the number of records in the file
*
* @param inNumRecords
* The number of records.
*/
public void setNumRecords(int inNumRecords) {
recordCnt = inNumRecords;
}
/**
* Write the header data to the DBF file.
*
* @param out
* A channel to write to. If you have an OutputStream you can
* obtain the correct channel by using
* java.nio.Channels.newChannel(OutputStream out).
* @throws IOException
* If errors occur.
*/
public void writeHeader(WritableByteChannel out) throws IOException {
// take care of the annoying case where no records have been added...
if (headerLength == -1) {
headerLength = MINIMUM_HEADER;
}
ByteBuffer buffer = ByteBuffer.allocateDirect(headerLength);
buffer.order(ByteOrder.LITTLE_ENDIAN);
// write the output file type.
buffer.put((byte) MAGIC);
// write the date stuff
Calendar c = Calendar.getInstance();
c.setTime(new Date());
buffer.put((byte) (c.get(Calendar.YEAR) % 100));
buffer.put((byte) (c.get(Calendar.MONTH) + 1));
buffer.put((byte) (c.get(Calendar.DAY_OF_MONTH)));
// write the number of records in the datafile.
buffer.putInt(recordCnt);
// write the length of the header structure.
buffer.putShort((short) headerLength);
// write the length of a record
buffer.putShort((short) recordLength);
// // write the reserved bytes in the header
// for (int i=0; i<20; i++) out.writeByteLE(0);
buffer.position(buffer.position() + 20);
// write all of the header records
int tempOffset = 0;
for (int i = 0; i < fields.length; i++) {
// write the field name
for (int j = 0; j < 11; j++) {
if (fields[i].fieldName.length() > j) {
buffer.put((byte) fields[i].fieldName.charAt(j));
} else {
buffer.put((byte) 0);
}
}
// write the field type
buffer.put((byte) fields[i].fieldType);
// // write the field data address, offset from the start of the
// record.
buffer.putInt(tempOffset);
tempOffset += fields[i].fieldLength;
// write the length of the field.
buffer.put((byte) fields[i].fieldLength);
// write the decimal count.
buffer.put((byte) fields[i].decimalCount);
// write the reserved bytes.
// for (in j=0; jj<14; j++) out.writeByteLE(0);
buffer.position(buffer.position() + 14);
}
// write the end of the field definitions marker
buffer.put((byte) 0x0D);
buffer.position(0);
int r = buffer.remaining();
while ((r -= out.write(buffer)) > 0) {
; // do nothing
}
NIOUtilities.clean(buffer);
}
/**
* Get a simple representation of this header.
*
* @return A String representing the state of the header.
*/
public String toString() {
StringBuffer fs = new StringBuffer();
for (int i = 0, ii = fields.length; i < ii; i++) {
DbaseField f = fields[i];
fs.append(f.fieldName + " " + f.fieldType + " " + f.fieldLength
+ " " + f.decimalCount + " " + f.fieldDataAddress + "\n");
}
return "DB3 Header\n" + "Date : " + date + "\n" + "Records : "
+ recordCnt + "\n" + "Fields : " + fieldCnt + "\n" + fs;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -