Example #1
0
  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.");
    }
  }
Example #2
0
  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();
    }
  }
Example #3
0
  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);
  }