private void readFieldDescriptors(LittleEndianInputStream is, int nFields) throws IOException { // read description of each field byte[] asciiFieldName = new byte[11]; for (int i = 0; i < nFields; i++) { DBFField field = new DBFField(); is.read(asciiFieldName); field.name = bytesToString(asciiFieldName, asciiFieldName.length, this.charsetName); field.type = is.readUnsignedByte(); field.address = is.readInt(); field.length = is.readUnsignedByte(); field.decimalCount = is.readUnsignedByte(); is.readShort(); // overread reserved value field.workAreaID = is.readUnsignedByte(); field.multiUserDBase = is.readShort(); field.setFields = is.readUnsignedByte(); is.skipBytes(7); // overread 7 reserved bytes field.fieldInMDXIndex = is.readUnsignedByte(); this.fields.add(field); this.printInfo("\n" + field.toString()); } // overread the Header Record Terminator, which should be 0x0D byte terminator = is.readByte(); if (terminator != 0x0D) { throw new IOException("DBF file is corrupt."); } }
private void readRecord(LittleEndianInputStream is, int recordSize, Table table) throws IOException { int deletedFlag = is.readUnsignedByte(); byte[] data = new byte[recordSize]; Vector rowData = new Vector(); java.util.Iterator iterator = this.fields.iterator(); while (iterator.hasNext()) { DBFField field = (DBFField) iterator.next(); is.read(data, 0, field.length); switch (field.type) { case 'C': // character string String string = bytesToString(data, field.length, charsetName); rowData.add(string.trim()); break; case 'F': // floating number try { rowData.add(new Double(new String(data, 0, field.length))); } catch (NumberFormatException exc) { rowData.add(this.DEFAULT_NUMBER); } break; case 'N': // number try { rowData.add(new Double(new String(data, 0, field.length))); } catch (NumberFormatException exc) { rowData.add(this.DEFAULT_NUMBER); } break; case '8': case 'O': // little endian 8 byte double. Not tested !!! ??? long byte1 = data[0]; long byte2 = data[1]; long byte3 = data[2]; long byte4 = data[3]; long byte5 = data[4]; long byte6 = data[5]; long byte7 = data[6]; long byte8 = data[7]; long l = (byte8 << 56) + (byte7 << 48) + (byte6 << 40) + (byte5 << 32) + (byte4 << 24) + (byte3 << 16) + (byte2 << 8) + byte1; rowData.add(new Double(Double.longBitsToDouble(l))); break; case '4': case 'I': // little endian 4 byte integer. Not tested !!! ??? int i = (data[3] << 24) + (data[2] << 16) + (data[1] << 8) + data[0]; rowData.add(new Double(i)); break; case '2': // little endian 2 byte integer. Not tested !!! ??? rowData.add(new Double((data[1] << 8) + data[0])); break; /* case 'D': // date System.out.println ("Date objects in DBF files not tested."); // !!! ??? // Date in format YYYYMMDD. if (field.length != 8) throw new Exception("Date object has non-standard length in DBF file."); int year = Integer.parseInt(new String(data, 0, 4)); int month = Integer.parseInt(new String(data, 4, 2)); int day = Integer.parseInt(new String(data, 6, 2)); Date date = new Date(year, month, day); rowData.add(date.toString()); break; case 'L': // logical // ? Not initialised (default) // Y,y Yes // N,n No // F,f False // T,t True final byte b = data[0]; if (b == 'Y' || b == 'y' || b == 'T' || b == 't') rowData.add("True"); else if (b == 'N' || b == 'n' || b == 'F' || b == 'f') rowData.add("False"); else rowData.add("?"); break; */ default: // add the raw bytes as String rowData.add(new String(data, 0, field.length)); ; } } table.addRow(rowData); }