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

ucar.nc2.iosp.NCheader Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 1998-2018 University Corporation for Atmospheric Research/Unidata
 * See LICENSE for license information.
 */

package ucar.nc2.iosp;

import java.io.IOException;

/**
 * Common header for netcdf3, netcdf4, hdf5, hdf4.
 *
 * @author dmh
 * @deprecated Will move to internal module in version 6.
 */

public class NCheader {
  //////////////////////////////////////////////////
  // Constants

  // Constants for check_file_type
  private static final int MAGIC_NUMBER_LEN = 8;
  private static final long MAXHEADERPOS = 50000; // header's gotta be within this range

  public static final byte[] H5HEAD = {(byte) 0x89, 'H', 'D', 'F', '\r', '\n', (byte) 0x1a, '\n'};
  public static final byte[] H4HEAD = {(byte) 0x0e, (byte) 0x03, (byte) 0x13, (byte) 0x01};
  public static final byte[] CDF1HEAD = {(byte) 'C', (byte) 'D', (byte) 'F', (byte) 0x01};
  public static final byte[] CDF2HEAD = {(byte) 'C', (byte) 'D', (byte) 'F', (byte) 0x02};
  public static final byte[] CDF5HEAD = {(byte) 'C', (byte) 'D', (byte) 'F', (byte) 0x05};

  // These should match the constants in netcdf-c/include/netcdf.h
  public static final int NC_FORMAT_NETCDF3 = (1);
  public static final int NC_FORMAT_64BIT_OFFSET = (2);
  public static final int NC_FORMAT_NETCDF4 = (3);
  public static final int NC_FORMAT_64BIT_DATA = (5);

  // Extensions
  public static final int NC_FORMAT_HDF4 = (0x7005);

  // Aliases
  public static final int NC_FORMAT_CLASSIC = (NC_FORMAT_NETCDF3);
  public static final int NC_FORMAT_64BIT = (NC_FORMAT_64BIT_OFFSET);
  public static final int NC_FORMAT_CDF5 = (NC_FORMAT_64BIT_DATA);
  public static final int NC_FORMAT_HDF5 = (NC_FORMAT_NETCDF4);

  //////////////////////////////////////////////////
  // Static Methods

  /**
   * Figure out what kind of netcdf-related file we have.
   * Constraint: leave raf read pointer to point just after the magic number.
   *
   * @param raf to test type
   * @return integer that matches constants in netcdf-c/include/netcdf.h
   */
  public static int checkFileType(ucar.unidata.io.RandomAccessFile raf) throws IOException {
    int format;

    byte[] magic = new byte[MAGIC_NUMBER_LEN];

    // If this is not an HDF5 file, then the magic number is at
    // position 0; If it is an HDF5 file, then we need to search
    // forward for it.

    // Look for the relevant leading tag
    raf.seek(0);
    if (raf.readBytes(magic, 0, MAGIC_NUMBER_LEN) < MAGIC_NUMBER_LEN)
      return 0; // unknown
    // Some version of CDF
    int hdrlen;
    hdrlen = CDF1HEAD.length; // all CDF headers are assumed to be same length
    format = 0;
    if (memequal(CDF1HEAD, magic, CDF1HEAD.length))
      format = NC_FORMAT_CLASSIC;
    else if (memequal(CDF2HEAD, magic, CDF2HEAD.length))
      format = NC_FORMAT_64BIT_OFFSET;
    else if (memequal(CDF5HEAD, magic, CDF5HEAD.length))
      format = NC_FORMAT_CDF5;
    else if (memequal(H4HEAD, magic, H4HEAD.length))
      format = NC_FORMAT_HDF4;
    if (format != 0) {
      raf.seek(hdrlen);
      return format;
    }
    // For HDF5, we need to search forward
    format = 0;
    long filePos = 0;
    long size = raf.length();
    while ((filePos < size - 8) && (filePos < MAXHEADERPOS)) {
      boolean match;
      raf.seek(filePos);
      if (raf.readBytes(magic, 0, MAGIC_NUMBER_LEN) < MAGIC_NUMBER_LEN)
        return 0; // unknown
      // Test for HDF5
      if (memequal(H5HEAD, magic, H5HEAD.length)) {
        format = NC_FORMAT_HDF5;
        break;
      }
      filePos = (filePos == 0) ? 512 : 2 * filePos;
    }
    if (format != 0)
      raf.seek(filePos + H5HEAD.length);
    return format;
  }

  /**
   * Not quite memcmp
   */
  private static boolean memequal(byte[] b1, byte[] b2, int len) {
    if (b1 == b2)
      return true;
    if (b1 == null || b2 == null)
      return false;
    if (b1.length < len || b2.length < len)
      return false;
    for (int i = 0; i < len; i++) {
      if (b1[i] != b2[i])
        return false;
    }
    return true;
  }

  public static String formatName(int format) {
    switch (format) {
      case NCheader.NC_FORMAT_NETCDF3:
        return "netcdf-3";
      case NCheader.NC_FORMAT_64BIT_OFFSET:
        return "netcdf-3 64bit-offset";
      case NCheader.NC_FORMAT_NETCDF4:
        return "netcdf-4";
      case NCheader.NC_FORMAT_64BIT_DATA:
        return "netcdf-5";
      case NCheader.NC_FORMAT_HDF4:
        return "HDF-4";
      default:
        break;
    }
    return null;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy