grib/src/main/java/ucar/nc2/grib/grib2/Grib2Index.java
public boolean makeIndex(String filename, RandomAccessFile dataRaf) throws IOException {
    String idxPath = filename;
    if (!idxPath.endsWith(GBX9_IDX)) idxPath += GBX9_IDX;
    File idxFile = GribIndexCache.getFileOrCache(idxPath);
    File idxFileTmp = GribIndexCache.getFileOrCache(idxPath + ".tmp");

    boolean ok = false;
    RandomAccessFile raf = null;

    try (FileOutputStream fout = new FileOutputStream(idxFileTmp)) {
      //// header message
      fout.write(MAGIC_START.getBytes(CDM.utf8Charset));
      NcStream.writeVInt(fout, version);

      Map<Long, Integer> gdsMap = new HashMap<>();
      gdsList = new ArrayList<>();
      records = new ArrayList<>(200);

      Grib2IndexProto.Grib2Index.Builder rootBuilder = Grib2IndexProto.Grib2Index.newBuilder();
      rootBuilder.setFilename(filename);

      if (dataRaf == null)  {
        raf = RandomAccessFile.acquire(filename);
        dataRaf = raf;
      }

      Grib2RecordScanner scan = new Grib2RecordScanner(dataRaf);
      while (scan.hasNext()) {
        Grib2Record r = scan.next();
        if (r == null) break; // done
        records.add(r);

        Grib2SectionGridDefinition gdss = r.getGDSsection();
        Integer index = gdsMap.get(gdss.calcCRC());
        if (index == null) {
          gdsList.add(gdss);
          index = gdsList.size()-1;
          gdsMap.put(gdss.calcCRC(), index);
          rootBuilder.addGdsList(makeGdsProto(gdss));
        }
        rootBuilder.addRecords(makeRecordProto(r, index, r.getGDS().scanMode));
      }

      if (records.isEmpty())
        throw new RuntimeException("No GRIB2 records found in "+dataRaf.getLocation());

      Grib2IndexProto.Grib2Index index = rootBuilder.build();
      byte[] b = index.toByteArray();
      NcStream.writeVInt(fout, b.length); // message size
      fout.write(b);  // message  - all in one gulp
      logger.debug("  made gbx9 index for {} size={}", filename, b.length);

      ok = true;
      return true;

    } finally {
      if (raf != null) raf.close(); // only close if we opened it

      // now switch; fout has been closed
      if (ok) {
        RandomAccessFile.eject(idxFile.getPath());
        boolean deleteOk = !idxFile.exists() || idxFile.delete();
        boolean renameOk = idxFileTmp.renameTo(idxFile);
        if (!deleteOk)
          logger.error("  could not delete Grib2Index= {}", idxFile.getPath());
        if (!renameOk)
          logger.error("  could not rename Grib2Index= {}", idxFile.getPath());
      }
    }
  }
public boolean makeIndex(String filename, RandomAccessFile dataRaf) throws IOException {
    String idxPath = filename;
    if (!idxPath.endsWith(GBX9_IDX)) idxPath += GBX9_IDX;
    File idxFile = GribIndexCache.getFileOrCache(idxPath);
    File idxFileTmp = GribIndexCache.getFileOrCache(idxPath + ".tmp");

    boolean ok = false;
    RandomAccessFile raf = null;

    try (FileOutputStream fout = new FileOutputStream(idxFileTmp)) {
      //// header message
      fout.write(MAGIC_START.getBytes(CDM.utf8Charset));
      NcStream.writeVInt(fout, version);

      Map<Long, Integer> gdsMap = new HashMap<>();
      gdsList = new ArrayList<>();
      records = new ArrayList<>(200);

      Grib2IndexProto.Grib2Index.Builder rootBuilder = Grib2IndexProto.Grib2Index.newBuilder();
      rootBuilder.setFilename(filename);

      if (dataRaf == null)  {
        raf = RandomAccessFile.acquire(filename);
        dataRaf = raf;
      }

      Grib2RecordScanner scan = new Grib2RecordScanner(dataRaf);
      while (scan.hasNext()) {
        Grib2Record r = scan.next();
        if (r == null) break; // done
        records.add(r);

        Grib2SectionGridDefinition gdss = r.getGDSsection();
        Integer index = gdsMap.get(gdss.calcCRC());
        if (index == null) {
          gdsList.add(gdss);
          index = gdsList.size()-1;
          gdsMap.put(gdss.calcCRC(), index);
          rootBuilder.addGdsList(makeGdsProto(gdss));
        }
        rootBuilder.addRecords(makeRecordProto(r, index, r.getGDS().scanMode));
      }

      if (records.isEmpty())
        throw new RuntimeException("No GRIB2 records found in "+dataRaf.getLocation());

      Grib2IndexProto.Grib2Index index = rootBuilder.build();
      byte[] b = index.toByteArray();
      NcStream.writeVInt(fout, b.length); // message size
      fout.write(b);  // message  - all in one gulp
      logger.debug("  made gbx9 index for {} size={}", filename, b.length);

      ok = true;
      return true;

    } finally {
      if (raf != null) raf.close(); // only close if we opened it

      // now switch; fout has been closed
      if (ok) {
        RandomAccessFile.eject(idxFile.getPath());
        boolean deleteOk = !idxFile.exists() || idxFile.delete();
        boolean renameOk = idxFileTmp.renameTo(idxFile);
        if (!deleteOk)
          logger.error("  could not delete Grib2Index= {}", idxFile.getPath());
        if (!renameOk)
          logger.error("  could not rename Grib2Index= {}", idxFile.getPath());
      }
    }
  }
LOOK what about extending an index ??