All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.tinfour.gis.shapefile.DbfFieldInt Maven / Gradle / Ivy

Go to download

Classes for accessing data from GIS sources including Shapefiles and airborne Lidar

There is a newer version: 2.1.7
Show newest version
/* --------------------------------------------------------------------
 * Copyright (C) 2018  Gary W. Lucas.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ---------------------------------------------------------------------
 */

 /*
 * -----------------------------------------------------------------------
 *
 * Revision History:
 * Date     Name         Description
 * ------   ---------    -------------------------------------------------
 * 12/2018  G. Lucas     Created  
 *
 * Notes:
 *
 * -----------------------------------------------------------------------
 */
package org.tinfour.gis.shapefile;

import java.io.IOException;
import java.util.Arrays;
import org.tinfour.io.BufferedRandomAccessReader;

/**
 * Extends DbfField with special handling for reading integer values.
 */
public class DbfFieldInt extends DbfField {

  private int value;

  DbfFieldInt(
          String name,
          char fieldType,
          int dataAddress,
          int fieldLength,
          int fieldDecimalCount,
          int offset) {
    super(name, fieldType, dataAddress, fieldLength, fieldDecimalCount, offset);
  }

  @Override
  void read(BufferedRandomAccessReader brad, long recordFilePos) throws IOException {
    brad.seek(recordFilePos + offset);
    builder.setLength(0);

    int i = 0;
    int sign = 1;
    long s = 0;

    // find first non-space character
    boolean foundDigit = false;
    while (i < fieldLength) {
      int b = brad.readUnsignedByte();
      builder.append((char) b);
      if (b == 32) {
        i++;
      } else if (b == '-') {
        sign = -1;
        i++;
        break;
      } else if (b == '+') {
        i++;
        break;
      } else if (48 <= b && b <= 57) {
        s = b - 48;
        i++;
        foundDigit = true;
        break;
      } else {
        // a non-whitespace character.  at this time,
        // the meaning of this is unknown.
        value = 0;
        throw new IOException(
                "Invalid integer value, unknown character "
                + ((char) b));
      }
    }

    if (!foundDigit) {
      throw new IOException("Invalid integer value, blank field");
    }

    // process the non-fractional part
    while (i < fieldLength) {
      int b = brad.readUnsignedByte();
      builder.append((char) b);
      if (48 <= b && b <= 57) {
        s = s * 10 + (b - 48);
      } else if (s == 32) {
        break;
      } else {
        value = 0;
        throw new IOException(
                "Invalid integer value, unknown character "
                + ((char) b));
      }
      i++;
    }

    s *= sign;

    if (s > Integer.MAX_VALUE) {
      value = Integer.MAX_VALUE;
      throw new IOException("Invalid integer value out of range " + s);
    } else if (s < Integer.MIN_VALUE) {
      value = Integer.MIN_VALUE;
      throw new IOException("Invalid integer value out of range " + s);
    }

    value = (int) s;

  }

  /**
   * Gets the double value stored in the field during the most recent read
   * operation, if any
   *
   * @return a valid double or a NaN if the file content was invalid
   */
  @Override
  public double getDouble() {
    return value;
  }

  /**
   * Gets the equivalent integer value of the field.
   *
   * @return a valid integral value, or a zero if undefined.
   */
  @Override
  public int getInteger() {
    return value;
  }

  @Override
  public Object getApplicationData() {
    return value;
  }

  /**
   * Gets an array of unique values for this field.
   *
   * @param dbf a valid instance
   * @return if successful an array of zero or more elements.
   * @throws IOException in the event of an unrecoverable I/O condition.
   */
  public int[] getUniqueValueArray(DbfFileReader dbf) throws IOException {
    int vMin = Integer.MAX_VALUE;
    int vMax = Integer.MIN_VALUE;
    int nRecords = dbf.getRecordCount();
    int[] vArray = new int[nRecords];
    if (nRecords == 0) {
      return new int[0];
    }

    int k = 0;
    for (int i = 1; i <= nRecords; i++) {
      dbf.readField(i, this);
      int v = getInteger();
      if (v < vMin) {
        vMin = v;
      }
      if (v > vMax) {
        vMax = v;
      }
      vArray[k++] = v;
    }

    Arrays.sort(vArray);
    int nUniqueValues = 1;
    int prior = vArray[0];
    for (int i = 1; i < nRecords; i++) {
      if (vArray[i] != prior) {
        prior = vArray[i];
        vArray[nUniqueValues] = vArray[i];
        nUniqueValues++;
      }
    }
    return Arrays.copyOf(vArray, nUniqueValues);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy