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."); } }
public Table read(String filePath) throws IOException { LittleEndianInputStream is = null; if (filePath == null) return null; try { // read all data into a data buffer. is = new LittleEndianInputStream(new BufferedInputStream(new FileInputStream(filePath))); int fileCode = unsignedByteToInt(is.readByte()); int year = unsignedByteToInt(is.readByte()); int month = unsignedByteToInt(is.readByte()); int day = unsignedByteToInt(is.readByte()); long nbrRecords = is.readInt(); // & 0xffffffffL;// unsigned int int headerSize = is.readShort(); int recordSize = is.readShort(); is.readShort(); // overread reserved value is.readByte(); // transaction byte int encrypted = is.readUnsignedByte(); // encription byte is.skipBytes(13); int codepage = is.readUnsignedByte(); is.skipBytes(2); // map the codepage to a string. Based on: // http://www.clicketyclick.dk/databases/xbase/format/dbf.html#DBF_STRUCT switch (codepage) { case 0x01: // DOS USA code page 437 this.charsetName = "IBM437"; break; case 0x02: // DOS Multilingual code page 850 this.charsetName = "IBM850"; break; case 0x03: // Windows ANSI code page 1252 this.charsetName = "windows-1252"; break; case 0x04: // Standard Macintosh this.charsetName = "MacRoman"; break; // ESRI shape files use code 0x57 to indicate that // data is written in ANSI (whatever that means). // http://www.esricanada.com/english/support/faqs/arcview/avfaq21.asp case 0x57: this.charsetName = "windows-1252"; break; case 0x64: // EE MS-DOS code page 852 this.charsetName = "IBM852"; break; case 0x65: // Nordic MS-DOS code page 865 this.charsetName = "IBM865"; break; case 0x66: // Russian MS-DOS code page 866 this.charsetName = "IBM866"; break; case 0x67: // Icelandic MS-DOS this.charsetName = "IBM861"; break; /* case 0x68: // Kamenicky (Czech) MS-DOS // ? break; case 0x69: // Mazovia (Polish) MS-DOS // ? break; */ case 0x6A: // Greek MS-DOS (437G) [?] this.charsetName = "x-IBM737"; break; case 0x6B: // Turkish MS-DOS this.charsetName = "IBM857"; break; case 0x96: // Russian Macintosh this.charsetName = "x-MacCyrillic"; break; case 0x97: // Eastern European Macintosh this.charsetName = "x-MacCentralEurope"; break; case 0x98: // Greek Macintosh this.charsetName = "x-MacGreek"; break; case 0xC8: // Windows EE (=Eastern Europe?) code page 1250 this.charsetName = "windows-1250"; break; case 0xC9: // Russian Windows this.charsetName = "windows-1251"; break; case 0xCA: // Turkish Windows this.charsetName = "windows-1254"; break; case 0xCB: // Greek Windows this.charsetName = "windows-1253"; break; default: this.charsetName = "IBM437"; } this.printInfo("File Code: " + fileCode); this.printInfo("Year: " + year); this.printInfo("Month: " + month); this.printInfo("Day: " + day); this.printInfo("Nbr Records: " + nbrRecords); this.printInfo("Header Size: " + headerSize); this.printInfo("Record Size: " + recordSize); this.printInfo("Ecrypted: " + encrypted); this.printInfo("Codepage: " + codepage); if (encrypted != 0) throw new IOException("Encrypted DBF not supported."); int nFields = (headerSize - 32) / 32; this.readFieldDescriptors(is, nFields); // create an new table Table table = this.initTable("ShapeAttributes"); // read the records and fill the table for (int i = 0; i < nbrRecords; i++) { this.printInfo("Reading Record " + i); this.readRecord(is, recordSize, table); } return table; } finally { if (is != null) is.close(); } }