ucar.atd.dorade.DoradeDescriptor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cdm Show documentation
Show all versions of cdm Show documentation
The NetCDF-Java Library is a Java interface to NetCDF files,
as well as to many other types of scientific data formats.
The newest version!
/*
* Copyright 1998-2014 University Corporation for Atmospheric Research/Unidata
*
* Portions of this software were developed by the Unidata Program at the
* University Corporation for Atmospheric Research.
*
* Access and use of this software shall impose the following obligations
* and understandings on the user. The user is granted the right, without
* any fee or cost, to use, copy, modify, alter, enhance and distribute
* this software, and any derivative works thereof, and its supporting
* documentation for any purpose whatsoever, provided that this entire
* notice appears in all copies of the software, derivative works and
* supporting documentation. Further, UCAR requests that the user credit
* UCAR/Unidata in any publications that result from the use of this
* software or in any product that includes this software. The names UCAR
* and/or Unidata, however, may not be used in any advertising or publicity
* to endorse or promote any products or commercial entity unless specific
* written permission is obtained from UCAR/Unidata. The user also
* understands that UCAR/Unidata is not obligated to provide the user with
* any support, consulting, training or assistance of any kind with regard
* to the use, operation and performance of this software nor to provide
* the user with any updates, revisions, new versions or "bug fixes."
*
* THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package ucar.atd.dorade;
import ucar.nc2.constants.CDM;
import ucar.nc2.time.CalendarDateFormatter;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.util.Date;
import java.util.TimeZone;
import java.util.HashMap;
abstract class DoradeDescriptor {
protected String descName;
protected String expectedName;
protected RandomAccessFile file;
protected boolean littleEndianData;
protected boolean verbose;
protected static final TimeZone TZ_UTC = TimeZone.getTimeZone("UTC");
private static boolean defaultVerboseState = false;
// map from descriptor names to per-class default verbose states
private static HashMap classVerboseStates = new HashMap<>();
static class DescriptorException extends Exception {
protected DescriptorException(String message) {
super(message);
}
protected DescriptorException(Throwable cause) {
super(cause);
}
}
/**
* Read and set the descriptor name, size, and endianness, and return the
* entire contents of the descriptor (including the name and size) as a
* byte array. The file position will be left at the beginning of the next
* descriptor (or at the end of file).
*
* @param file the DORADE sweepfile, positioned at the beginning of a
* descriptor
* @param littleEndianData set to true iff the file contains little-endian
* data
* @param expectedName the expected name for the descriptor being read
* @throws DescriptorException for file read errors, descriptor name
* mismatch, etc.
*/
protected byte[] readDescriptor(RandomAccessFile file,
boolean littleEndianData,
String expectedName)
throws DescriptorException {
this.file = file;
this.littleEndianData = littleEndianData;
this.expectedName = expectedName;
verbose = getDefaultVerboseState(expectedName);
byte[] data;
try {
//
// find the next descriptor with our expected name
//
findNext(file);
//
// keep track of the start of this descriptor
//
long startpos = file.getFilePointer();
//
// get the name and descriptor size
//
byte[] header = new byte[8];
file.readFully(header);
descName = new String(header, 0, 4, CDM.utf8Charset);
int size = grabInt(header, 4);
//
// now back up to the start of the descriptor and read the entire
// thing into a byte array
//
file.seek(startpos);
data = new byte[size];
file.readFully(data);
} catch (java.io.IOException ex) {
throw new DescriptorException(ex);
}
//
// now check the name we got against the expected name
//
if (!descName.equals(expectedName))
throw new DescriptorException("Got descriptor name '" + descName +
"' when expecting name '" +
expectedName + "'");
return data;
}
/**
* Skip the current DORADE descriptor in the file, leaving the file position
* at the beginning of the next descriptor (or at the end of file).
*
* @param file the DORADE sweepfile, positioned at the beginning of a
* descriptor
* @throws java.io.IOException
*/
protected static void skipDescriptor(RandomAccessFile file,
boolean littleEndianData)
throws DescriptorException, java.io.IOException {
try {
file.readFully(new byte[4]); // skip name
byte[] lenBytes = new byte[4];
file.readFully(lenBytes);
int descLen = grabInt(lenBytes, 0, littleEndianData);
file.readFully(new byte[descLen - 8]);
} catch (java.io.EOFException eofex) {
return; // just leave the file at EOF
} catch (Exception ex) {
throw new DescriptorException(ex);
}
}
/**
* Return the name of the DORADE descriptor at the current location
* in the file. The current location will not be changed.
*
* @param file the DORADE sweep file, positioned at the beginning of a
* descriptor
* @return the name of the DORADE descriptor starting at the current
* file position, or null if no descriptor name is available
* @throws DescriptorException
*/
protected static String peekName(RandomAccessFile file)
throws DescriptorException {
try {
long filepos = file.getFilePointer();
byte[] nameBytes = new byte[4];
if (file.read(nameBytes) == -1)
return null; // EOF
file.seek(filepos);
return new String(nameBytes, CDM.utf8Charset);
} catch (IOException ex) {
throw new DescriptorException(ex);
}
}
/**
* Determine if the given DORADE sweepfile contains little-endian data
* (in violation of the DORADE definition...).
*
* @param file the DORADE sweepfile,
* @return true
iff the file contains little-endian data
* @throws DescriptorException
*/
public static boolean sweepfileIsLittleEndian(RandomAccessFile file)
throws DescriptorException {
int descLen;
try {
file.seek(0);
//
// skip the 4-byte descriptor name
//
byte[] bytes = new byte[4];
file.readFully(bytes);
//
// get the descriptor length
//
descLen = file.readInt();
file.seek(0);
} catch (Exception ex) {
throw new DescriptorException(ex);
}
return (descLen < 0 || descLen > 0xffffff);
}
/**
* Unpack a two-byte integer from the given byte array.
*
* @param bytes byte array to be read
* @param offset number of bytes to skip in the byte array before reading
* @return the unpacked short value
*/
protected short grabShort(byte[] bytes, int offset) {
int ndx0 = offset + (littleEndianData ? 1 : 0);
int ndx1 = offset + (littleEndianData ? 0 : 1);
// careful that we only allow sign extension on the highest order byte
return (short) (bytes[ndx0] << 8 | (bytes[ndx1] & 0xff));
}
/**
* Unpack a four-byte integer from the given byte array.
*
* @param bytes byte array to be read
* @param offset number of bytes to skip in the byte array before reading
* @param littleEndianData true iff the byte array contains little-endian
* data
* @return the unpacked integer value
*/
protected static int grabInt(byte[] bytes, int offset,
boolean littleEndianData) {
int ndx0 = offset + (littleEndianData ? 3 : 0);
int ndx1 = offset + (littleEndianData ? 2 : 1);
int ndx2 = offset + (littleEndianData ? 1 : 2);
int ndx3 = offset + (littleEndianData ? 0 : 3);
// careful that we only allow sign extension on the highest order byte
return (bytes[ndx0] << 24 |
(bytes[ndx1] & 0xff) << 16 |
(bytes[ndx2] & 0xff) << 8 |
(bytes[ndx3] & 0xff));
}
/**
* Unpack a four-byte integer from the given byte array.
*
* @param bytes byte array to be read
* @param offset number of bytes to skip in the byte array before reading
* @return the unpacked integer value
*/
protected int grabInt(byte[] bytes, int offset) {
return grabInt(bytes, offset, littleEndianData);
}
/**
* Unpack a four-byte IEEE float from the given byte array.
*
* @param bytes byte array to be read
* @param offset number of bytes to skip in the byte array before reading
* @return the unpacked float value
*/
protected float grabFloat(byte[] bytes, int offset)
throws DescriptorException {
try {
byte[] src;
if (littleEndianData) {
src = new byte[4];
src[0] = bytes[offset + 3];
src[1] = bytes[offset + 2];
src[2] = bytes[offset + 1];
src[3] = bytes[offset];
offset = 0;
} else {
src = bytes;
}
DataInputStream stream =
new DataInputStream(new ByteArrayInputStream(src, offset, 4));
return stream.readFloat();
} catch (Exception ex) {
throw new DescriptorException(ex);
}
}
/**
* Unpack an eight-byte IEEE float from the given byte array.
*
* @param bytes byte array to be read
* @param offset number of bytes to skip in the byte array before reading
* @return the unpacked double value
*/
protected double grabDouble(byte[] bytes, int offset)
throws DescriptorException {
try {
byte[] src;
if (littleEndianData) {
src = new byte[8];
src[0] = bytes[offset + 7];
src[1] = bytes[offset + 6];
src[2] = bytes[offset + 5];
src[3] = bytes[offset + 4];
src[4] = bytes[offset + 3];
src[5] = bytes[offset + 2];
src[6] = bytes[offset + 1];
src[7] = bytes[offset];
offset = 0;
} else {
src = bytes;
}
DataInputStream stream =
new DataInputStream(new ByteArrayInputStream(src, offset, 8));
return stream.readDouble();
} catch (Exception ex) {
throw new DescriptorException(ex);
}
}
protected static long findNextWithName(String expectedName,
RandomAccessFile file,
boolean littleEndianData)
throws DescriptorException, java.io.IOException {
//
// Skip forward through the file until we find a descriptor with
// the expected name
//
String descName;
while ((descName = peekName(file)) != null) {
if (descName.equals(expectedName)) {
try {
return file.getFilePointer();
} catch (java.io.IOException ex) {
throw new DescriptorException(ex);
}
}
skipDescriptor(file, littleEndianData);
}
throw new DescriptorException("Expected " + expectedName +
" descriptor not found!");
}
protected long findNext(RandomAccessFile file)
throws DescriptorException, java.io.IOException {
return findNextWithName(expectedName, file, littleEndianData);
}
/**
* Return a string with a reasonable and complete representation of the
* given Date
, shown in UTC.
*
* @param date Date
to be represented
* @return a string containing the representation of the date
*/
public static String formatDate(Date date) {
return CalendarDateFormatter.toDateTimeString(date);
}
/**
* Get the default verbose state for new DoradeDescriptor
-s.
*/
public static boolean getDefaultVerboseState() {
return defaultVerboseState;
}
/**
* Set the default verbose state for new DoradeDescriptor
-s.
*
* @param verbose the new default verbose state
*/
public static void setDefaultVerboseState(boolean verbose) {
defaultVerboseState = verbose;
classVerboseStates.clear();
}
/**
* Get the default verbose state for new DoradeDescriptor
-s
* of the given name.
*
* @param descriptorName the descriptor name for which the new default
* verbose state will apply
*/
public static boolean getDefaultVerboseState(String descriptorName) {
Boolean classVerboseState = classVerboseStates.get(descriptorName.toUpperCase());
if (classVerboseState != null)
return classVerboseState;
else
return defaultVerboseState;
}
/**
* Set the default verbose state for new DoradeDescriptor
-s
* of the given name.
*
* @param descriptorName the descriptor name for which the new default
* verbose state will apply
* @param verbose the new default verbose state
*/
public static void setDefaultVerboseState(String descriptorName,
boolean verbose) {
classVerboseStates.put(descriptorName.toUpperCase(), verbose);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy