Java Code Examples for ucar.unidata.io.RandomAccessFile#getFilePointer()

The following examples show how to use ucar.unidata.io.RandomAccessFile#getFilePointer() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: Grib2SectionGridDefinition.java    From netcdf-java with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
/**
 * Read Grib Definition section from raf.
 *
 * @param raf RandomAccessFile, with pointer at start of section
 * @throws java.io.IOException on I/O error
 * @throws IllegalArgumentException if not a GRIB-2 record
 */
public Grib2SectionGridDefinition(RandomAccessFile raf) throws IOException {

  startingPosition = raf.getFilePointer();

  // octets 1-4 (Length of GDS)
  int length = GribNumbers.int4(raf);

  // octet 5
  int section = raf.read(); // This is section 3
  if (section != 3)
    throw new IllegalArgumentException("Not a GRIB-2 GDS section");

  // octets 13-14
  raf.skipBytes(7);
  templateNumber = GribNumbers.uint2(raf);

  // read in whole GDS as byte[]
  rawData = new byte[length];
  raf.seek(startingPosition);
  raf.readFully(rawData);
}
 
Example 2
Source File: Grib2SectionDataRepresentation.java    From netcdf-java with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
public Grib2SectionDataRepresentation(RandomAccessFile raf) throws IOException {
  startingPosition = raf.getFilePointer();

  // octets 1-4 (Length of DRS)
  length = GribNumbers.int4(raf);
  if (length == 0)
    throw new IllegalArgumentException("Not a GRIB-2 Data representation section");

  // octet 5
  int section = raf.read();
  if (section != 5)
    throw new IllegalArgumentException("Not a GRIB-2 Data representation section");

  // octets 6-9 number of datapoints
  dataPoints = GribNumbers.int4(raf);

  // octet 10
  int dt = GribNumbers.uint2(raf);
  dataTemplate = (dt == 40000) ? 40 : dt; // ?? NCEP bug ??

  raf.seek(startingPosition + length);
}
 
Example 3
Source File: Grib1SectionGridDefinition.java    From netcdf-java with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
/**
 * Read Grib Definition section from raf.
 *
 * @param raf RandomAccessFile, with pointer at start of section
 * @throws java.io.IOException on I/O error
 * @throws IllegalArgumentException if not a GRIB-2 record
 */
public Grib1SectionGridDefinition(RandomAccessFile raf) throws IOException {

  startingPosition = raf.getFilePointer();

  // octets 1-3 (Length of GDS)
  int length = GribNumbers.int3(raf);

  // octet 6
  raf.skipBytes(2);
  gridTemplate = GribNumbers.uint(raf);

  // read in whole GDS as byte[]
  rawData = new byte[length];
  raf.seek(startingPosition);
  raf.readFully(rawData);

  predefinedGridDefinition = -1;
  predefinedGridDefinitionCenter = -1;
}
 
Example 4
Source File: Grib2SectionIndicator.java    From netcdf-java with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
/**
 * Read Grib2SectionIndicator from raf.
 *
 * @param raf RandomAccessFile, with pointer at start (the "GRIB")
 * @throws java.io.IOException on I/O error
 * @throws IllegalArgumentException if not a GRIB-2 record
 */
public Grib2SectionIndicator(RandomAccessFile raf) throws IOException {
  startPos = raf.getFilePointer();
  byte[] b = new byte[4];
  raf.readFully(b);
  for (int i = 0; i < b.length; i++)
    if (b[i] != MAGIC[i])
      throw new IllegalArgumentException("Not a GRIB record");

  raf.skipBytes(2);
  discipline = raf.read();
  int edition = raf.read();
  if (edition != 2)
    throw new IllegalArgumentException("Not a GRIB-2 record");

  messageLength = GribNumbers.int8(raf);
}
 
Example 5
Source File: H5objects.java    From netcdf-java with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
/**
 * Read a zero terminated String at current position; advance file to a multiple of 8.
 *
 * @param raf from this file
 * @return String (dont include zero terminator)
 * @throws IOException on io error
 */
private String readString8(RandomAccessFile raf) throws IOException {
  long filePos = raf.getFilePointer();

  int count = 0;
  while (raf.readByte() != 0)
    count++;

  raf.seek(filePos);
  byte[] s = new byte[count];
  raf.readFully(s);

  // skip to 8 byte boundary, note zero byte is skipped
  count++;
  count += padding(count, 8);
  raf.seek(filePos + count);

  return new String(s, StandardCharsets.UTF_8); // all Strings are UTF-8 unicode
}
 
Example 6
Source File: Grib1SectionIndicator.java    From netcdf-java with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
/**
 * Read Grib2SectionIndicator from raf.
 *
 * @param raf RandomAccessFile, with pointer at start (the "GRIB")
 * @throws java.io.IOException on I/O error
 * @throws IllegalArgumentException if not a GRIB-2 record
 */
Grib1SectionIndicator(RandomAccessFile raf) throws IOException {
  startPos = raf.getFilePointer();
  byte[] b = new byte[4];
  raf.readFully(b);
  for (int i = 0; i < b.length; i++)
    if (b[i] != MAGIC[i])
      throw new IllegalArgumentException("Not a GRIB record");

  messageLengthNotFixed = GribNumbers.uint3(raf);
  int edition = raf.read();
  if (edition != 1)
    throw new IllegalArgumentException("Not a GRIB-1 record");
  messageLength = Grib1RecordScanner.getFixedTotalLengthEcmwfLargeGrib(raf, messageLengthNotFixed);
  if (messageLength != messageLengthNotFixed) {
    isMessageLengthFixed = true;
  }
}
 
Example 7
Source File: Grib2Drs.java    From netcdf-java with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
Type50002(RandomAccessFile raf) throws IOException {
  // according to https://github.com/erdc-cm/grib_api/blob/master/definitions/grib2/template.5.50002.def
  this.referenceValue = raf.readFloat();
  this.binaryScaleFactor = GribNumbers.int2(raf);
  this.decimalScaleFactor = GribNumbers.int2(raf);
  this.numberOfBits = raf.read();
  this.widthOfFirstOrderValues = raf.read();
  this.p1 = GribNumbers.int4(raf);
  this.p2 = GribNumbers.int4(raf);
  this.widthOfWidth = raf.read();
  this.widthOfLength = raf.read();
  this.boustrophonic = raf.read();
  this.orderOfSPD = raf.read();
  this.widthOfSPD = raf.read();
  this.spd = new int[orderOfSPD + 1];
  BitReader bitReader = new BitReader(raf, raf.getFilePointer());
  for (int i = 0; i < orderOfSPD; i++) {
    this.spd[i] = (int) bitReader.bits2UInt(widthOfSPD);
  }
  this.spd[orderOfSPD] = (int) bitReader.bits2SInt(widthOfSPD);
  this.lengthOfSection6 = GribNumbers.int4(raf);
  this.section6 = raf.read();
  this.bitMapIndicator = raf.read();
  this.lengthOfSection7 = GribNumbers.int4(raf);
  this.section7 = raf.read();
}
 
Example 8
Source File: BufrSplitter.java    From netcdf-java with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
public Message getMessage(RandomAccessFile raf) throws IOException {
  raf.seek(4);
  BufrIndicatorSection is = new BufrIndicatorSection(raf);
  BufrIdentificationSection ids = new BufrIdentificationSection(raf, is);
  BufrDataDescriptionSection dds = new BufrDataDescriptionSection(raf);

  long dataPos = raf.getFilePointer();
  int dataLength = BufrNumbers.uint3(raf);
  BufrDataSection dataSection = new BufrDataSection(dataPos, dataLength);

  if ((is.getBufrEdition() > 4) || (is.getBufrEdition() < 2)) {
    logger.warn("Edition " + is.getBufrEdition() + " is not supported");
    bad_msgs++;
    return null;
  }

  return new Message(raf, is, ids, dds, dataSection);
}
 
Example 9
Source File: Grib1RecordScanner.java    From netcdf-java with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
static int getFixedTotalLengthEcmwfLargeGrib(RandomAccessFile raf, int len) throws IOException {
  int lenActual = len;
  if ((len & 0x800000) == 0x800000) {
    long pos0 = raf.getFilePointer(); // remember the actual pos
    int lenS1 = GribNumbers.uint3(raf); // section1Length
    raf.skipBytes(1); // table2Version
    if (GribNumbers.uint(raf) == 98) { // center (if ECMWF make the black magic)
      raf.skipBytes(2); // generatingProcessIdentifier, gridDefinition
      int s1f = GribNumbers.uint(raf); // section1Flags
      raf.skipBytes(lenS1 - (3 + 5)); // skips to next section
      int lenS2;
      int lenS3;
      if ((s1f & 128) == 128) { // section2 GDS exists
        lenS2 = GribNumbers.uint3(raf); // section2Length
        raf.skipBytes(lenS2 - 3); // skips to next section
      }
      if ((s1f & 64) == 64) { // section3 BMS exists
        lenS3 = GribNumbers.uint3(raf); // section3Length
        raf.skipBytes(lenS3 - 3); // skips to next section
      }
      int lenS4 = GribNumbers.uint3(raf); // section4Length
      if (lenS4 < 120) { // here we are!!!!
        lenActual = (len & 0x7FFFFF) * 120 - lenS4 + 4; // the actual totalLength
      }
    }
    raf.seek(pos0); // recall the pos
  }
  return lenActual;
}
 
Example 10
Source File: Grib2RecordScanner.java    From netcdf-java with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
/**
 * tricky bit of business. recapture the entire record based on drs position.
 * for validation.
 * 
 * @param raf from this RandomAccessFile
 * @param drsPos Grib2SectionDataRepresentation starts here
 */
@Nullable
public static Grib2Record findRecordByDrspos(RandomAccessFile raf, long drsPos) throws IOException {
  long pos = Math.max(0, drsPos - (20 * 1000)); // go back 20K
  Grib2RecordScanner scan = new Grib2RecordScanner(raf, pos);
  while (scan.hasNext()) {
    ucar.nc2.grib.grib2.Grib2Record gr = scan.next();
    Grib2SectionDataRepresentation drs = gr.getDataRepresentationSection();
    if (drsPos == drs.getStartingPosition())
      return gr;
    if (raf.getFilePointer() > drsPos)
      break; // missed it.
  }
  return null;
}
 
Example 11
Source File: Grib2SectionData.java    From netcdf-java with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
public Grib2SectionData(RandomAccessFile raf) throws IOException {
  startingPosition = raf.getFilePointer();

  // octets 1-4 (Length of section)
  msgLength = GribNumbers.int4(raf);

  // octet 5
  int section = raf.read();
  if (section != 7)
    throw new IllegalStateException("Not a Grib2SectionData (section 7)");

  // skip to end of the data section
  raf.seek(startingPosition + msgLength);
}
 
Example 12
Source File: BufrDataDescriptionSection.java    From netcdf-java with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
/**
 * Constructs a BufrDataDescriptionSection object by reading section 3 from a BUFR file.
 *
 * @param raf RandomAccessFile, position must be on a BUFR section 3
 * @throws IOException on read error
 */
public BufrDataDescriptionSection(RandomAccessFile raf) throws IOException {
  offset = raf.getFilePointer();
  int length = BufrNumbers.uint3(raf);
  long EOS = offset + length;

  // reserved byte
  raf.read();

  // octets 5-6 number of datasets
  ndatasets = BufrNumbers.uint2(raf);

  // octet 7 data type bit 2 is for compressed data 192 or 64,
  // non-compressed data is 0 or 128
  datatype = raf.read();

  // get descriptors
  int ndesc = (length - 7) / 2;
  for (int i = 0; i < ndesc; i++) {
    int ch1 = raf.read();
    int ch2 = raf.read();
    short fxy = (short) ((ch1 << 8) + (ch2));
    descriptors.add(fxy);
  }

  // reset for any offset discrepancies
  raf.seek(EOS);
}
 
Example 13
Source File: H5header.java    From netcdf-java with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
/**
 * Read a zero terminated String. Leave file positioned after zero terminator byte.
 *
 * @param raf from this file
 * @return String (dont include zero terminator)
 * @throws java.io.IOException on io error
 */
private String readString(RandomAccessFile raf) throws IOException {
  long filePos = raf.getFilePointer();

  int count = 0;
  while (raf.readByte() != 0)
    count++;

  raf.seek(filePos);
  String result = raf.readString(count);
  raf.readByte(); // skip the zero byte! nn
  return result;
}
 
Example 14
Source File: H5objects.java    From netcdf-java with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
/**
 * Read a zero terminated String. Leave file positioned after zero terminator byte.
 *
 * @param raf from this file
 * @return String (dont include zero terminator)
 * @throws IOException on io error
 */
private String readString(RandomAccessFile raf) throws IOException {
  long filePos = raf.getFilePointer();

  int count = 0;
  while (raf.readByte() != 0)
    count++;

  raf.seek(filePos);
  String result = raf.readString(count);
  raf.readByte(); // skip the zero byte! nn
  return result;
}
 
Example 15
Source File: Grib1SectionBinaryData.java    From netcdf-java with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
Grib1SectionBinaryData(RandomAccessFile raf) throws IOException {
  startingPosition = raf.getFilePointer();

  // octets 1-3 (Length of section)
  length = GribNumbers.uint3(raf);
  // if (length < 0)
  // throw new IllegalStateException("GRIB record has bad length, pos = " + startingPosition);
  raf.seek(startingPosition + length);
}
 
Example 16
Source File: Cinrad2Record.java    From netcdf-java with BSD 3-Clause "New" or "Revised" License 4 votes vote down vote up
public void readSCHeader(RandomAccessFile din) throws IOException {

    message_offset = 0;
    din.seek(message_offset);
    // site info 170
    din.skipBytes(90);
    byte[] b10 = new byte[10];
    // Message Header
    din.read(b10);
    String stationNId = new String(b10);

    din.skipBytes(52);

    // latlon
    int lon = din.readInt();
    int lat = din.readInt();
    int hhh = din.readInt();

    din.skipBytes(6);
    //
    message_type = 1;

    // PerformanceInfo
    din.skipBytes(31);

    // ObservationInfo
    vcp = convertunsignedByte2Short(din.readByte());
    short syear = (short) din.readUnsignedShort();
    short smm = convertunsignedByte2Short(din.readByte());
    short sdd = convertunsignedByte2Short(din.readByte());
    short shh = convertunsignedByte2Short(din.readByte());
    short smi = convertunsignedByte2Short(din.readByte());
    short sss = convertunsignedByte2Short(din.readByte());

    dateTime0 = CalendarDate.of(null, syear, smm, sdd, shh, smi, sss);

    din.skipBytes(8);
    long offset = din.getFilePointer();
    sweepInfo = new SweepInfo[30];
    for (int i = 0; i < 30; i++) {
      sweepInfo[i] = new SweepInfo(din, (int) offset);
      offset = offset + 21;
    }

    din.skipBytes(6);

    syear = (short) din.readUnsignedShort();
    smm = convertunsignedByte2Short(din.readByte());
    sdd = convertunsignedByte2Short(din.readByte());
    shh = convertunsignedByte2Short(din.readByte());
    smi = convertunsignedByte2Short(din.readByte());
    sss = convertunsignedByte2Short(din.readByte());

    dateTimeE = CalendarDate.of(null, syear, smm, sdd, shh, smi, sss);

  }
 
Example 17
Source File: Grib1DataReader.java    From netcdf-java with BSD 3-Clause "New" or "Revised" License 4 votes vote down vote up
private static void showOffset(Formatter f, String what, RandomAccessFile raf, long startPos, int expectOffset)
    throws IOException {
  int offset = (int) (raf.getFilePointer() - startPos);
  f.format("%s: filePos=%d, offset=%d expect=%d%n", what, raf.getFilePointer(), offset, expectOffset);
}
 
Example 18
Source File: Grib1DataReader.java    From netcdf-java with BSD 3-Clause "New" or "Revised" License 4 votes vote down vote up
public static void showComplexPackingInfo(Formatter f, RandomAccessFile raf, long startPos) throws IOException {
  GribData.Info info = Grib1SectionBinaryData.getBinaryDataInfo(raf, startPos);

  if (!info.isGridPointData() || info.isSimplePacking())
    return;

  int N1 = GribNumbers.uint2(raf);
  int flagExt = raf.read();
  boolean hasBitmap2 = GribNumbers.testGribBitIsSet(flagExt, 3);
  boolean hasDifferentWidths = GribNumbers.testGribBitIsSet(flagExt, 4);
  boolean useGeneralExtended = GribNumbers.testGribBitIsSet(flagExt, 5);
  boolean useBoustOrdering = GribNumbers.testGribBitIsSet(flagExt, 6);

  int N2 = GribNumbers.uint2(raf);
  int codedNumberOfGroups = GribNumbers.uint2(raf);
  int numberOfSecondOrderPackedValues = GribNumbers.uint2(raf);
  int extraValues = raf.read();
  int NG = codedNumberOfGroups + 65536 * extraValues;
  int widthOfWidths = raf.read();
  int widthOfLengths = raf.read();
  int NL = GribNumbers.uint2(raf);

  f.format("%n");
  f.format("       ----flagExt = %s%n", Long.toBinaryString(flagExt));
  f.format("        hasBitmap2 = %s%n", hasBitmap2);
  f.format("hasDifferentWidths = %s%n", hasDifferentWidths);
  f.format("useGeneralExtended = %s%n", useGeneralExtended);
  f.format("  useBoustOrdering = %s%n", useBoustOrdering);
  f.format("                NL = %d%n", NL);
  f.format("                N1 = %d%n", N1);
  f.format("                N2 = %d%n", N2);
  f.format("    numberOfGroups = %d%n", NG);
  f.format("     widthOfWidths = %d%n", widthOfWidths);
  f.format("    widthOfLengths = %d%n", widthOfLengths);
  f.format("%n");

  int groupWidthsSizeBits = widthOfWidths * NG;
  int groupWidthsSizeBytes = (groupWidthsSizeBits + 7) / 8;
  int skipBytes = NL - groupWidthsSizeBytes - 26;
  raf.skipBytes(skipBytes);

  BitReader reader = new BitReader(raf, raf.getFilePointer());
  int[] groupWidth = new int[NG];
  for (int group = 0; group < NG; group++) {
    groupWidth[group] = (int) reader.bits2UInt(widthOfWidths);
  }
  reader.incrByte(); // assume on byte boundary
  showOffset(f, "GroupLength", raf, startPos, NL - 1);

  // try forcing to NL
  // reader = new BitReader(raf, this.startPos + NL - 1);

  // meta groupLengths unsigned_bits(widthOfLengths,numberOfGroups) : read_only;
  int[] groupLength = new int[NG];
  for (int group = 0; group < NG; group++)
    groupLength[group] = (int) reader.bits2UInt(widthOfLengths);
  showOffset(f, "FirstOrderValues", raf, startPos, N1 - 1);

  // meta countOfGroupLengths sum(groupLengths);
  int countOfGroupLengths = 0;
  for (int group = 0; group < NG; group++)
    countOfGroupLengths += groupLength[group];
  f.format("countOfGroupLengths = %d%n", countOfGroupLengths);

  // try forcing to N1
  // reader = new BitReader(raf, this.startPos + N1 - 1);

  // First-order descriptors width stored at the equivalent place of bit number for ordinary packing
  int foWidth = info.numberOfBits;

  // meta firstOrderValues unsigned_bits(widthOfFirstOrderValues,numberOfGroups) : read_only;
  reader.incrByte(); // assume on byte boundary
  int[] firstOrderValues = new int[NG];
  for (int group = 0; group < NG; group++)
    firstOrderValues[group] = (int) reader.bits2UInt(foWidth);

  showOffset(f, "SecondOrderValues", raf, startPos, N2 - 1);

  int total_nbits = 0;
  for (int group = 0; group < NG; group++) {
    int nbits = groupLength[group] * groupWidth[group];
    total_nbits += nbits;
  }
  int data_bytes = (total_nbits + 7) / 8;
  f.format(" total_nbits=%d, nbytes=%d%n", total_nbits, data_bytes);
  f.format(" expect msgLen=%d, actual=%d%n", N2 - 1 + data_bytes, info.dataLength);
  // int simplepackSizeInBits = nPts * info.numberOfBits;
  // int simplepackSizeInBytes = (simplepackSizeInBits +7) / 8;
  // f.format(" simplepackSizeInBits=%d, simplepackSizeInBytes=%d%n", simplepackSizeInBits, simplepackSizeInBytes);
  logger.debug("{}", f);
}
 
Example 19
Source File: Grib2SectionIdentification.java    From netcdf-java with BSD 3-Clause "New" or "Revised" License 4 votes vote down vote up
/**
 * Read Grib2SectionIndicator from raf.
 *
 * @param raf RandomAccessFile, with pointer at start of indicator section
 * @throws java.io.IOException on I/O error
 * @throws IllegalArgumentException if not a GRIB-2 record
 */
public Grib2SectionIdentification(RandomAccessFile raf) throws IOException {
  long sectionEnd = raf.getFilePointer();

  // section 1 octet 1-4 (length of section)
  int length = GribNumbers.int4(raf);
  sectionEnd += length;

  int section = raf.read();
  if (section != 1)
    throw new IllegalArgumentException("Not a GRIB-2 Identification section");

  // Center octet 6-7
  center_id = GribNumbers.int2(raf);

  // subCenter octet 8-9
  subcenter_id = GribNumbers.int2(raf);

  // master table octet 10 (code table 1.0)
  master_table_version = raf.read();

  // local table octet 11 (code table 1.1)
  local_table_version = raf.read();

  // significanceOfRT octet 12 (code table 1.1)
  significanceOfRT = raf.read();

  // octets 13-19 (reference time of forecast)
  year = GribNumbers.int2(raf);
  month = raf.read();
  day = raf.read();
  hour = raf.read();
  minute = raf.read();
  second = raf.read();
  // refTime = CalendarDate.of(null, year, month, day, hour, minute, second);

  productionStatus = raf.read();
  processedDataType = raf.read();

  raf.seek(sectionEnd);
}
 
Example 20
Source File: NmcObsLegacy.java    From netcdf-java with BSD 3-Clause "New" or "Revised" License 4 votes vote down vote up
boolean readId(RandomAccessFile raf) throws IOException {

      filePos = raf.getFilePointer();
      byte[] reportId = raf.readBytes(40);
      String latS = new String(reportId, 0, 5, StandardCharsets.UTF_8);

      if (latS.equals("END R")) {
        raf.skipBytes(-40);
        endRecord(raf);

        filePos = raf.getFilePointer();
        reportId = raf.readBytes(40);
        latS = new String(reportId, 0, 5, StandardCharsets.UTF_8);
      }
      if (latS.equals("ENDOF")) {
        raf.skipBytes(-40);
        if (!endFile(raf))
          return false;

        filePos = raf.getFilePointer();
        reportId = raf.readBytes(40);
        latS = new String(reportId, 0, 5, StandardCharsets.UTF_8);
      }

      try {
        lat = (float) (.01 * Float.parseFloat(latS));
        lon = (float) (360.0 - .01 * Float.parseFloat(new String(reportId, 5, 5, StandardCharsets.UTF_8)));

        stationId = new String(reportId, 10, 6, StandardCharsets.UTF_8);
        obsTime = Short.parseShort(new String(reportId, 16, 4, StandardCharsets.UTF_8));
        System.arraycopy(reportId, 20, reserved, 0, 7);
        reportType = Short.parseShort(new String(reportId, 27, 3, StandardCharsets.UTF_8));
        elevMeters = Float.parseFloat(new String(reportId, 30, 5, StandardCharsets.UTF_8));
        instType = Short.parseShort(new String(reportId, 35, 2, StandardCharsets.UTF_8));
        reportLen = 10 * Integer.parseInt(new String(reportId, 37, 3, StandardCharsets.UTF_8));

        cal.setTime(refDate);
        int hour = cal.get(Calendar.HOUR_OF_DAY);
        if (obsTime / 100 > hour + 4) // if greater than 4 hours from reference time
          cal.add(Calendar.DAY_OF_MONTH, -1); // subtract a day LOOK
        cal.set(Calendar.HOUR_OF_DAY, obsTime / 100);
        cal.set(Calendar.MINUTE, 6 * (obsTime % 100));
        date = cal.getTime();

        if (showObs)
          System.out.println(this);
        else if (showTime)
          System.out.print("  time=" + obsTime + " date= " + dateFormatter.toDateTimeString(date));

        // nobs++;
        raf.skipBytes(reportLen - 40);
        return reportLen < 30000;

      } catch (IOException e) {
        throw new IOException("BAD reportId=" + new String(reportId, StandardCharsets.UTF_8) + " starts at " + filePos);
      }
    }