/*
* GribFile.java
*
* Created on April 28, 2005, 8:21 PM
*
* $Id: GribFile.java 16 2006-08-24 19:50:37Z gabriel $
*
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Viperfish.
*
* The Initial Developer of the Original Code is Gabriel Galibourg.
* Portions created by Gabriel Galibourg are Copyright (C) 2005-2006
* Gabriel Galibourg. All Rights Reserved.
*
* Contributor(s):
*
*/
package com.solfin.grib;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.EOFException;
import java.util.Iterator;
import java.util.Vector;
import java.nio.channels.FileChannel;
/**
* This class manipulates GRIB files.
* These are made of one or several records which are managed by the
* GribRecord class.
* @author gabriel
*/
public class GribFile implements Iterable<GribRecord> {
private File gribFile;
private GribParameter[] arrParameters=null;
private GribRecord[] arrRecords=null; // just the PDS of each record in the GRIB file
private Long[] arrRecordsPos=null; // the starting bytes offset of each record in the GRIB file.
/**
* Open a GRIB file provided by the <tt>File</tt> descriptor.
* @param gribFile the GRIB file representation.
*/
public GribFile(File gribFile) {
if (gribFile==null)
throw new NullPointerException("file parameter in GribFile(file) constructor is null");
this.gribFile=gribFile;
Vector<GribRecord> vRecords = new Vector<GribRecord>();
Vector<Long> vRecordsPos=new Vector<Long>();
try {
FileInputStream in = new FileInputStream(gribFile);
FileChannel fCh=in.getChannel();
GribRecord gr=null;
while (in.available() > 0) {
gr=new GribRecord(in, 1);
vRecords.add(gr); // read up to (and incl) the PDS section
vRecordsPos.add(new Long(fCh.position()-gr.getLength()));
}
} catch (BadGribException e) {
return;
} catch (FileNotFoundException e) {
return;
} catch (IOException e) {
return;
}
//System.err.println("vRecords="+vRecords);
System.err.println("vRecordPos="+vRecordsPos);
arrRecords=vRecords.toArray(new GribRecord[0]);
arrRecordsPos=vRecordsPos.toArray(new Long[0]);
}
/**
* Returns the number of records contained in the GRIB file.
* @return the number of records
*/
public int getNbRecords() {
return arrRecords.length;
}
/**
* Retrieve <tt>iRecord</tt>'th record of the GRIB file.
* This method is more optimised than scanning through the GribRecord iterator because it
* just skips directly to the beginning of the record (the starting position of each
* record is stored in an internal array).
* @param iRecord the record indice number
* @return a GRIB record of the file or null if <tt>iRecord</tt> is invalid (negative or too large).
* @throws com.solfin.grib.BadGribException thrown in case of bad GRIB data.
*/
public GribRecord getRecord(int iRecord) throws BadGribException {
long pos=arrRecordsPos[iRecord];
try {
FileInputStream in = new FileInputStream(gribFile);
GribRecord gr;
in.skip(pos);
gr = new GribRecord(in);
in.close();
return gr;
} catch (FileNotFoundException e) {
return null;
} catch (IOException e) {
return null;
}
}
/**
* Method for iterating through all the records of this GRIB file.
* @return A GribRecord iterator
*/
public Iterator<GribRecord> iterator() {
return iterator(null);
}
/**
* Method for iterating through some of the records of this GRIB file.
* The records selected will be filtered with the GribRecordFiler.
* @param grf The GRIB filter that must be applied to each records
* and that this iterator will show (or not).
* @return a GribRecord iterator.
*/
public Iterator<GribRecord> iterator(final GribRecordFilter grf) {
final FileInputStream fin;
try {
fin = new FileInputStream(gribFile);
} catch (FileNotFoundException e) {
// very odd but can happen if file is deleted after it was first seen and
// analysed by the Grib library.
return null;
}
return new Iterator<GribRecord>() {
GribRecord nextRecord=null;
public boolean hasNext() {
if (nextRecord != null)
return true;
while (true) {
nextRecord = null; // this is not obvious (see loop below)
try {
if (fin.available()<=0) {
fin.close();
return false;
}
} catch (Exception e) {
System.err.println("Exception in GribFile.iterator.hasNext: "+e);
return false;
}
try {
nextRecord = new GribRecord(fin);
} catch (BadGribException e) {
System.err.println("I'm in the catch of BadGribException:"+e);
nextRecord=null;
try {
fin.close();
} catch (Exception e2) {}
return false;
} catch (EOFException e) {
System.err.println("in the catch of EOF:"+e);
nextRecord=null;
try {
fin.close();
} catch (Exception e2) {}
return false;
} catch (IOException e) {
nextRecord=null;
try {
fin.close();
} catch (Exception e2) {}
return false;
}
if (grf==null || grf.accept(nextRecord))
return true;
}
}
public GribRecord next() {
if (nextRecord==null)
hasNext();
if (!hasNext())
return null;
if (nextRecord!=null) {
GribRecord currentRecord = nextRecord;
nextRecord = null;
return currentRecord;
}
return null;
}
public void remove() {
// do nothing
}
};
}
/**
* Returns a vector of all the parameters stored in this GRIB file.
* Parameters will most probably occur several times in the GRIB
* file, but the returned vector will only show each parameter once.
* Beware however that parameters are not sorted in any way.
* @return the vector of GribParameters
*/
public GribParameter[] getParametersArray() {
if (arrParameters == null) {
Vector<GribParameter> vParams = new Vector<GribParameter>();
for (int i=0 ; i<arrRecords.length ; ++i) {
GribRecord gr = arrRecords[i];
if (!vParams.contains(gr.getParameter())) {
vParams.add(gr.getParameter());
}
}
arrParameters=vParams.toArray(new GribParameter[0]);
}
return arrParameters;
}
// /**
// * Test method
// */
// public static void main(String[] args) {
// GribFile gf = GribFile.open("full.grb"); //args[0]);
// int grNb=1;
// for (GribRecord gr : gf) {
// System.out.println("Record:"+ grNb++ +"\n"+gr.toString());
// int iVal=0;
// for (GribValue gv : gr) {
// System.out.println("bds["+iVal+"]="+gv.toString()+" ");
// iVal++;
// }
// }
//
// Calendar aTime = new GregorianCalendar(2005,3,30,12,00);
// aTime.setTimeZone(TimeZone.getTimeZone("GMT"));
// System.out.println("aDate="+GribTools.printDateTime(aTime));
//
// grNb=1;
// Iterator<GribRecord> gri = gf.iterator(new GribRecordFilter(aTime));
// GribRecord gr;
// while ( (gr=gri.next())!=null ) {
// System.out.println("Record:"+ grNb++ +" "+ gr.getCenterId() +" "+gr.getParameterId() + " " + GribTools.printDateTime(gr.getForecastDate1()));
// }
//
// }
}