protected Header readHeaderFromBuffer(ByteBuffer buffer) throws WWRuntimeException {
    // Read file code - first byte
    int fileCode = buffer.get();
    if (fileCode > 5) {
      String message = Logging.getMessage("SHP.NotADBaseFile", file.getPath());
      Logging.logger().log(java.util.logging.Level.SEVERE, message);
      throw new WWRuntimeException(message);
    }

    // Last update date
    int yy = 0xFF & buffer.get(); // unsigned
    int mm = buffer.get();
    int dd = buffer.get();

    // Number of records
    int numRecords = buffer.getInt();

    // Header struct length
    int headerLength = buffer.getShort();

    // Record length
    int recordLength = buffer.getShort();

    // Assemble header
    Header header = new Header();
    header.fileCode = fileCode;
    Calendar cal = Calendar.getInstance();
    cal.set(1900 + yy, mm - 1, dd);
    header.lastModificationDate = cal.getTime();
    header.numberOfRecords = numRecords;
    header.headerLength = headerLength;
    header.recordLength = recordLength;

    return header;
  }
  /**
   * Read block from file.
   *
   * @param file - File to read.
   * @param off - Marker position in file to start read from if {@code -1} read last blockSz bytes.
   * @param blockSz - Maximum number of chars to read.
   * @param lastModified - File last modification time.
   * @return Read file block.
   * @throws IOException In case of error.
   */
  public static VisorFileBlock readBlock(File file, long off, int blockSz, long lastModified)
      throws IOException {
    RandomAccessFile raf = null;

    try {
      long fSz = file.length();
      long fLastModified = file.lastModified();

      long pos = off >= 0 ? off : Math.max(fSz - blockSz, 0);

      // Try read more that file length.
      if (fLastModified == lastModified && fSz != 0 && pos >= fSz)
        throw new IOException(
            "Trying to read file block with wrong offset: " + pos + " while file size: " + fSz);

      if (fSz == 0)
        return new VisorFileBlock(file.getPath(), pos, fLastModified, 0, false, EMPTY_FILE_BUF);
      else {
        int toRead = Math.min(blockSz, (int) (fSz - pos));

        byte[] buf = new byte[toRead];

        raf = new RandomAccessFile(file, "r");

        raf.seek(pos);

        int cntRead = raf.read(buf, 0, toRead);

        if (cntRead != toRead)
          throw new IOException(
              "Count of requested and actually read bytes does not match [cntRead="
                  + cntRead
                  + ", toRead="
                  + toRead
                  + ']');

        boolean zipped = buf.length > 512;

        return new VisorFileBlock(
            file.getPath(), pos, fSz, fLastModified, zipped, zipped ? zipBytes(buf) : buf);
      }
    } finally {
      U.close(raf, null);
    }
  }
  public List<DBaseRecord> getRecords() {
    if (this.records == null && this.getFile() != null) {
      File file = this.getFile();
      try {
        this.records = this.readRecordsFromFile(file);
      } catch (Exception e) {
        String message = Logging.getMessage("SHP.ExceptionAttemptingToReadFile", file.getPath());
        Logging.logger().log(java.util.logging.Level.SEVERE, message, e);
        throw new WWRuntimeException(message, e);
      }
    }

    return this.records;
  }
  public DBaseFile(File file) {
    if (file == null) {
      String message = Logging.getMessage("nullValue.FileIsNull");
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }

    this.file = file;
    try {
      this.header = this.readHeaderFromFile(file);
      this.fields = this.readFieldsFromBuffer(this.header.fieldsHeaderBuffer);
      // Delay records loading until getRecords() is called.
    } catch (Exception e) {
      String message = Logging.getMessage("SHP.ExceptionAttemptingToReadFile", file.getPath());
      Logging.logger().log(java.util.logging.Level.SEVERE, message, e);
      throw new WWRuntimeException(message, e);
    }
  }
 public static void unhideFile(File path) throws IOException, InterruptedException {
   String[] args = {path.getPath()};
   Process p = Runtime.getRuntime().exec(args);
   p.waitFor();
 }