最近做的一个B/S项目,有一个功能的要求是鼠标在地图上框选一个坐标范围,读取这个坐标范围内的.hdf文件数据,然后将读取出来的数据信息供用户浏览下载。我在开发的时候也是遇到了很多问题,上网查阅了大量的资料最后才解决了问题,参考的博客,网站:
http://blog.csdn.net/liminlu0314/article/details/6937194
http://blog.csdn.net/mygisforum/article/details/22478491
http://www.gdal.org/gdal_tutorial.html
首先是动态链接库的问题,用gdal读取.hdf文件首先要添加下图中的dll,具体的dll的下载方式网上有很多我就不在这里一一赘述了,我给大家几个关于gdal dll文件的链接
http://www.gisinternals.com/
需要添加的dll文件:
添加的位置:
虽然只是SXYService代码块使用了类库,但是SBSGIS.Web中也要添加这些dll,将这16个dll拷贝到SBSGIS.Web的bin目录下和SXYService的Debug目录下只有这两个项目中都有这些dll最后才能运行成功,然后将这些文件中以_csharp.dll 文件结尾的添加到SXYService和SBSGIS.Web的项目引用中去,然后再需要读取数据操作的类中引入如下命名空间using OSGeo.GDAL; 以下代码就不会在运行的时候出错了。
C# 读取HDF4数据集数据
namespace ReadHDF4
{
class Program
{
static void Main(string[] args)
{
OSGeo.GDAL.Gdal.AllRegister();//注册所有的格式驱动
OSGeo.GDAL.Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");//支持中文路径和名称
string hdfFileName = @"D:\NOAA16_AVHRR_20030301_SNC_Td.hdf";
//打开hdf文件
Dataset dsFile = Gdal.Open(hdfFileName, Access.GA_ReadOnly);
if (dsFile == null)
{
Console.WriteLine("不能打开该文件,请检查文件是否存在");
return;
}
//获取存储的子数据集的路径描述信息数据列表
/*数据集信息按顺序按对排列:
* SUBDATASET_1_NAME=HDF4_SDS:UNKNOWN:\"D:\\NOAA16_AVHRR_20030301_SNC_Td.hdf\":0
* SUBDATASET_1_DESC=[5000x8000] 10Day_CMG_Max_Snow_Cover (8-bit unsigned integer)
* SUBDATASET_2_NAME=HDF4_SDS:UNKNOWN:\"D:\\NOAA16_AVHRR_20030301_SNC_Td.hdf\":1
* SUBDATASET_2_DESC=[5000x8000] 10Day_CMG_Max_Snow_Cover_Date (8-bit unsigned integer)
*/
string[] subDataSets = dsFile.GetMetadata("SUBDATASETS");
dsFile.Dispose();
string dsName = "10Day_CMG_Max_Snow_Cover";
//根据数据集名称获取数据集名称信息
string dataSetInfo = "";
for(int i=0; i<subDataSets.Length; i++){
string[] descInfo = subDataSets[i].Split(' ');
if (descInfo.Length>1)
{
foreach (string s in descInfo)
{
if (s.Equals(dsName))
{
dataSetInfo = subDataSets[i - 1];
}
}
}
}
//取”SUBDATASET_1_NAME=”后面的内容,并去除“””
dataSetInfo = dataSetInfo.Split('=')[1].Replace("\"", "");
//根据SUBDATASET_1_NAME打开数据集
Dataset ds = Gdal.Open(dataSetInfo, Access.GA_ReadOnly);
if(ds == null){
Console.WriteLine("不能打开该数据集,请检查数据集是否存在!");
return;
}
//读取数据集信息
Band demband = ds.GetRasterBand(1);
int[] databuf = new int[5000 * 8000];
demband.ReadRaster(0, 0, ds.RasterXSize, ds.RasterYSize, databuf, ds.RasterXSize, ds.RasterYSize, 0, 0);//读取数据
Console.WriteLine(databuf[8000*33+460]);
//读取属性值
string attr = ds.GetMetadataItem("units",null);
ds.Dispose();
Console.ReadLine();
}
}
}
如果使用gdal正确的csharp 版本的dll文件是不会引发“OSGeo.GDAL.GdalPINVOKE”的类型初始值设定项引发异常。的问题。
如果有这个问题就需要你去编译一个csharp版本的dll,如果你实在找不到解决的方式也可以给我留言或者留下你的联系方式,我给你发送一份。
如果你在本地成功运行了上述的代码,但是你在发布到iis中再运行程序的的时候会发现走到了第一句注册所有格式驱动的时候会报错。经常在调用Gdal.AllRegister()方法时会抛出如下异常: