// return true if got another repeat out of this record // side effect is that the new record is in repeatRecord private boolean nextRepeating() throws IOException { raf.seek(repeatPos); // octets 1-4 (Length of GDS) int length = GribNumbers.int4(raf); int section = raf.read(); raf.seek(repeatPos); if (section == 2) { repeatRecord.setLus(new Grib2SectionLocalUse(raf)); repeatRecord.setGdss(new Grib2SectionGridDefinition(raf)); repeatRecord.setPdss(new Grib2SectionProductDefinition(raf)); repeatRecord.setDrs(new Grib2SectionDataRepresentation(raf)); repeatRecord.setBms(new Grib2SectionBitMap(raf), false); repeatRecord.setDataSection(new Grib2SectionData(raf)); repeatRecord.repeat = section; } else if (section == 3) { repeatRecord.setGdss(new Grib2SectionGridDefinition(raf)); repeatRecord.setPdss(new Grib2SectionProductDefinition(raf)); repeatRecord.setDrs(new Grib2SectionDataRepresentation(raf)); repeatRecord.setBms(new Grib2SectionBitMap(raf), false); repeatRecord.setDataSection(new Grib2SectionData(raf)); repeatRecord.repeat = section; } else if (section == 4) { repeatRecord.setPdss(new Grib2SectionProductDefinition(raf)); repeatRecord.setDrs(new Grib2SectionDataRepresentation(raf)); repeatRecord.setBms(new Grib2SectionBitMap(raf), false); repeatRecord.setDataSection(new Grib2SectionData(raf)); repeatRecord.repeat = section; } else { if (debugRepeat) System.out.printf(" REPEAT Terminate %d%n", section); repeatPos = -1; repeatRecord = null; repeatBms = null; return false; } // look for repeating bms Grib2SectionBitMap bms = repeatRecord.getBitmapSection(); if (bms.getBitMapIndicator() == 254) { // replace BMS with last good one if (repeatBms == null) throw new IllegalStateException("No bms in repeating section"); repeatRecord.setBms(repeatBms, true); // debug if (debugRepeat) System.out.printf("replaced bms %d%n", section); repeatRecord.repeat += 1000; } else if (bms.getBitMapIndicator() == 0) { // track last good bms repeatBms = repeatRecord.getBitmapSection(); } // keep only unique gds if ((section == 2) || (section == 3)) { // look for duplicate gds Grib2SectionGridDefinition gds = repeatRecord.getGDSsection(); long crc = gds.calcCRC(); Grib2SectionGridDefinition gdsCached = gdsMap.get(crc); if (gdsCached != null) repeatRecord.setGdss(gdsCached); else gdsMap.put(crc, gds); } // check to see if we are at the end long pos = raf.getFilePointer(); long ending = repeatRecord.getIs().getEndPos(); if (pos + 34 < ending) { // give it 30 bytes of slop if (debugRepeat) System.out.printf(" REPEAT AGAIN %d != %d%n", pos + 4, ending); repeatPos = pos; return true; } if (debug) System.out.printf( " REPEAT read until %d grib ending at %d header ='%s'%n", raf.getFilePointer(), ending, StringUtil2.cleanup(header)); // check that end section is correct raf.seek(ending - 4); for (int i = 0; i < 4; i++) { if (raf.read() != 55) { log.warn( " REPEAT Missing End of GRIB message at pos=" + ending + " header= " + StringUtil2.cleanup(header) + " for=" + raf.getLocation()); break; } } lastPos = raf.getFilePointer(); if (debugRepeat) System.out.printf(" REPEAT DONE%n"); repeatPos = -1; // no more repeats in this record return true; }
public Grib2Record next() throws IOException { if (repeatRecord != null) { // serve current repeatRecord if it exists return new Grib2Record(repeatRecord); } Grib2SectionIndicator is = null; try { is = new Grib2SectionIndicator(raf); Grib2SectionIdentification ids = new Grib2SectionIdentification(raf); Grib2SectionLocalUse lus = new Grib2SectionLocalUse(raf); Grib2SectionGridDefinition gds = new Grib2SectionGridDefinition(raf); Grib2SectionProductDefinition pds = new Grib2SectionProductDefinition(raf); Grib2SectionDataRepresentation drs = new Grib2SectionDataRepresentation(raf); Grib2SectionBitMap bms = new Grib2SectionBitMap(raf); Grib2SectionData dataSection = new Grib2SectionData(raf); if (dataSection.getMsgLength() > is.getMessageLength()) { // presumably corrupt raf.seek(drs.getStartingPosition()); // go back to before the dataSection throw new IllegalStateException("Illegal Grib2SectionData Message Length"); } // look for duplicate gds long crc = gds.calcCRC(); Grib2SectionGridDefinition gdsCached = gdsMap.get(crc); if (gdsCached != null) gds = gdsCached; else gdsMap.put(crc, gds); // look for duplicate pds /* crc = pds.calcCRC(); Grib2SectionProductDefinition pdsCached = pdsMap.get(crc); if (pdsCached != null) pds = pdsCached; else pdsMap.put(crc, pds); */ // check to see if we have a repeating record long pos = raf.getFilePointer(); long ending = is.getEndPos(); if (pos + 34 < ending) { // give it 30 bytes of slop if (debugRepeat) System.out.printf(" REPEAT AT %d != %d%n", pos + 4, ending); repeatPos = pos; repeatRecord = new Grib2Record( header, is, ids, lus, gds, pds, drs, bms, dataSection, false); // this assumes immutable sections // track bms in case its a repeat if (bms.getBitMapIndicator() == 0) repeatBms = bms; return new Grib2Record( repeatRecord); // GribRecord isnt immutable; still may not be necessary } if (debug) System.out.printf( " read until %d grib ending at %d header ='%s'%n", raf.getFilePointer(), ending, StringUtil2.cleanup(header)); // check that end section is correct raf.seek(ending - 4); for (int i = 0; i < 4; i++) { if (raf.read() != 55) { log.warn( "Missing End of GRIB message at pos=" + ending + " header= " + StringUtil2.cleanup(header) + " for=" + raf.getLocation()); break; } } lastPos = raf.getFilePointer(); return new Grib2Record(header, is, ids, lus, gds, pds, drs, bms, dataSection, false); } catch (Throwable t) { long pos = (is == null) ? -1 : is.getStartPos(); log.warn("Bad GRIB2 record in file {}, skipping pos={}", raf.getLocation(), pos); lastPos = raf.getFilePointer(); if (hasNext()) // skip forward return next(); } return null; // last record was incomplete }