java读取⽓象专业格式NetCDF⽂件
⼀、NetCDF简介
NetCDF全称为network Common Data Format( “⽹络通⽤数据格式”),是⼀个软件库与机器⽆关的数据格式,⽀持创建,访问基于数组的科研数据。分别提供了对Java和C / C++ / Fortran语⾔。对程序员来说,它和zip、jpeg、bmp⽂件格式类似,都是⼀种⽂件格式的标准。netcdf⽂件开始的⽬的是⽤于存储⽓象科学中的数据,现在已经成为许多数据采集软件的⽣成⽂件的格式。
从数学上来说,netcdf存储的数据就是⼀个多⾃变量的单值函数。⽤公式来说就是f(x,y,z,…)=value, 函数的⾃变量x,y,z等在netcdf中叫做维(dimension)或坐标轴(axix),函数值value在netcdf中叫做变量(Variables)。⽽⾃变量和函数值在物理学上的⼀些性质,⽐如计量单位(量纲)、物理学名称在netcdf中就叫属性(Attributes)。
⼆、需要⽤到的netcdf的jar
下载地址:
本⽂使⽤版本:netcdfAll-4.6.14.jar
需要java 的jdk 8以上版本
三、读取和打印经纬度变量,了解数据组织结构
public static void main(String[] args) {
String filename = "pres_";
NetcdfFile dataFile = null;
try {
dataFile = NetcdfFile.open(filename, null);
// Get the latitude and longitude Variables.
Variable latVar = dataFile.findVariable("latitude");
Variable lonVar = dataFile.findVariable("longitude");
System.out.println(NCdumpW.printVariableData(latVar, null));
System.out.println(NCdumpW.printVariableData(lonVar, null));
ArrayFloat.D1 latArray;
ArrayFloat.D1 lonArray;
latArray = (ArrayFloat.D1) ad();
lonArray = (ArrayFloat.D1) ad();
System.out.println(NCdumpW.printArray(latArray, "lat", null));
System.out.println(NCdumpW.printArray(lonArray, "lon", null));
// The file is closed no matter what by putting inside a try/catch block.
} catch (java.io.IOException e) {
e.printStackTrace();
return;
} catch (InvalidRangeException e) {
e.printStackTrace();
return;
} finally {
if (dataFile != null)
try {
dataFile.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
System.out.println("*** SUCCESS reading example file " + filename);
}
NC数据格式:经度:从左到右(正⾛),纬度:从下到上(正⾛)
.read():是读取这个变量所有的数据。
四、读取所有格点数据实例
@Override
public Map<String,Object> getNCDataFromFlex(String searchDate,String elementName,String levelType)
{
DecimalFormat decimalFormat=new DecimalFormat(".00");//构造⽅法的字符格式这⾥如果⼩数不⾜2位,会以0补⾜
//接⼝需求:经度:从左到右(正⾛),纬度:从上到下(负⾛)
//NC数据格式:经度:从左到右(正⾛),纬度:从下到上(正⾛)
String flex_nc_Instance().GetProperty("flex_nc_dir");
Map<String, Object> item = new HashMap<String, Object>();
int rows=73;
int cols=73;
item.put("cols", rows);
item.put("rows", cols);
item.put("startLon",113.35373);//sart到end,是⼩到⼤
item.put("startLat",37.99601);//sart到end,是⼤到⼩
item.put("endLon",115.84625);
item.put("endLat",36);
item.put("stepLon",0.034);//0.034
item.put("stepLat",-0.027);
item.put("missValue",0);
String filePath="";
float [][] uArray = new float[rows][cols];
float [][] vArray = new float[rows][cols];
//NC数据格式:经度:从左到右(正⾛),纬度:从下到上(正⾛)
NetcdfFile dataFile = null;
try {
String dateStr="";
Date times=DateUtil.strToDate(searchDate,"yyyyMMddHHmmss");
int Hours();
if(hour>=6)//早上6点以后就⽤当天的结果
{
hour=hour+1;
dateStr=DateUtil.dateToStr(times,"yyyyMMddHHmmss").substring(0,8);
}
filePath=flex_nc_dir+dateStr+"/"+dateStr+".nc";
log.info(filePath);
dataFile = NetcdfFile.open(filePath, null);
int[] origin = new int[]{hour, 0, 0};//开始位置:时间,经度,纬度
int[] size = new int[]{1, rows, cols};//数据⼤⼩:时间,经度,纬度
//输出UV
Variable u_Var = dataFile.findVariable("U10");
Variable v_Var = dataFile.findVariable("V10");
float[] u_Array=(float[])  ad(origin, size).copyTo1DJavaArray();
float[] v_Array=(float[])  ad(origin, size).copyTo1DJavaArray();
for(int i = 0 ; i < rows; i=i+1)
{
for(int j = 0; j< cols; j = j+1 )
{
uArray[rows-i-1][j] = Float.parseFloat(decimalFormat.format(u_Array[i *cols +j]));
vArray[i][j] = Float.parseFloat(decimalFormat.format(v_Array[i *cols +j]));
}
}
} catch (java.io.IOException e) {
e.printStackTrace();
return null;
} catch (InvalidRangeException e) {
e.printStackTrace();
return null;
}finally {
if (dataFile != null)
try {
dataFile.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
item.put("uArrays",uArray);
item.put("vArrays",vArray);
return item;
}
read(origin, size):是根据开始位置origin开始读取,然后读取size数据量的数据出来。
.copyTo1DJavaArray():是将多维变量转换成⼀维数组。
五、根据点位所在的经纬度,读取该位置的变量值
@Override
public Map<String,Object> getNCFactorFromFlex(String searchDate,float lon,float lat)
{
DecimalFormat decimalFormat=new DecimalFormat(".00");//构造⽅法的字符格式这⾥如果⼩数不⾜2位,会以0补⾜        //接⼝需求:经度:从左到右(正⾛),纬度:从上到下(负⾛)
//NC数据格式:经度:从左到右(正⾛),纬度:从下到上(正⾛)
String flex_nc_Instance().GetProperty("flex_nc_dir");
int rows=73;
int cols=73;
String filePath="";
float u_value=0;
float v_value=0;
float p_value=0;
float rh_value=0;
//NC数据格式:经度:从左到右(正⾛),纬度:从下到上(正⾛)
NetcdfFile dataFile = null;
try {
String dateStr="";
Date times=DateUtil.strToDate(searchDate,"yyyyMMddHHmmss");
int Hours();
if(hour>=6)//早上6点以后就⽤times当天的结果
{
hour=hour+1;
dateStr=DateUtil.dateToStr(times,"yyyyMMddHHmmss").substring(0,8);
}
else//上6点前就⽤times前⼀天的结果
{
hour=hour+24+1;
dateStr=DateUtil.dateToStr(DateUtil.dateAdd(times,"d",-1),"yyyyMMddHHmmss").substring(0,8);            }
filePath=flex_nc_dir+dateStr+"/"+dateStr+".nc";
log.info("getNCFactorFromFlex"+filePath);
dataFile = NetcdfFile.open(filePath, null);
//00开始,读取第⼀个⽹格,⽤于计算经度序号,纬度序号
int[] origin0 = new int[]{0, 0, 0};//开始位置:时间序号,经度序号,纬度序号
int[] size0 = new int[]{1, 73, 73};//数据⼤⼩:时间,经度,纬度
Variable x_Var = dataFile.findVariable("XLONG");
Variable y_Var = dataFile.findVariable("XLAT");
float[] x_Array=(float[])  ad(origin0, size0).copyTo1DJavaArray();
float[] y_Array=(float[])  ad(origin0, size0).copyTo1DJavaArray();
int x_xh=getLonXHfromNetcdf(x_Array,lon);
int y_xh=getLatXHfromNetcdf(y_Array,lat);
int[] origin = new int[]{hour, x_xh, y_xh};//开始位置:时间序号,经度序号,纬度序号
int[] size = new int[]{1, 1, 1};//数据⼤⼩:时间,经度,纬度
Variable u_Var = dataFile.findVariable("U10");
Variable v_Var = dataFile.findVariable("V10");
Variable p_Var = dataFile.findVariable("PSFC");
Variable rh_Var = dataFile.findVariable("rh2");
float[] u_Array=(float[])  ad(origin, size).copyTo1DJavaArray();
float[] v_Array=(float[])  ad(origin, size).copyTo1DJavaArray();
float[] p_Array=(float[])  ad(origin, size).copyTo1DJavaArray();
float[] rh_Array=(float[])  ad(origin, size).copyTo1DJavaArray();
u_value=u_Array[0];
v_value=v_Array[0];
p_value=p_Array[0];
rh_value=rh_Array[0];
} catch (java.io.IOException e) {
e.printStackTrace();
} catch (InvalidRangeException e) {
e.printStackTrace();
}finally {
if (dataFile != null)
try {
dataFile.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
Map<String, Object> WindSpeed(u_value,v_value);
item.put("u_value",Numberdf.format(u_value));springframework jar包下载
item.put("v_value",Numberdf.format(v_value));
item.put("p_value",und(p_value/100));
item.put("rh_value",und(rh_value));
return item;
}
public int getLonXHfromNetcdf(float[] x_arr,float lon)
{
//纬度数据,列:从前到后,变⼤;⾏:从前到后,不变,所以只需要遍历第1⾏的所有列即可int lon_xh=0;
int rows=73;
int cols=73;
for(int i = 0; i< 1; i = i+1 )
{
for(int j = 0; j< cols; j = j+1 )
{
float temp=x_arr[i *cols+j];
if(temp>lon)
{
lon_xh=j;
return lon_xh;
}
}
}
return lon_xh;
}
public int getLatXHfromNetcdf(float[] y_arr,float lat)
{
//纬度数据,列:从前到后,不变;⾏:从前到后,变⼤,所以只需要遍历第1列的所有⾏即可int lat_xh=0;
int rows=73;
int cols=73;
for(int i = 0; i< rows; i = i+1 )
{
for(int j = 0; j< 1; j = j+1 )
{
float temp=y_arr[i *cols+j];
if(temp>lat)
{
lat_xh=i;
return lat_xh;
}
}
}
return lat_xh;
}
其他读取⽅法
// read 3D array for that index
ArrayFloat.D3 presArray, tempArray;
presArray = (ArrayFloat.D3) (ad(origin, shape).reduce());
tempArray = (ArrayFloat.D3) (ad(origin, shape).reduce());
// now checking the value
int count = 0;
for (int lvl = 0; lvl < NLVL; lvl++)
for (int lat = 0; lat < NLAT; lat++)
for (int lon = 0; lon < NLON; lon++) {
if (((lvl, lat, lon) != SAMPLE_PRESSURE + count) ||
((lvl, lat, lon) != SAMPLE_TEMP + count))
}
}

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。