C#中使用gdal读取.hdf文件(包括vs中运行,iis中部署出现的部分问题)

  最近做的一个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()方法时会抛出如下异常:

“OSGeo.GDAL.GdalPINVOKE”的类型初始值设定项引发异常。
这个时候也是比较麻烦的时候,你会想明明我在vs中成功的运行了此项目但是为什么,部署到服务器中就不能使用了呢,这其实是缺少了动态链接库,你可以使用DEPENDS检查依赖项工具,检查一下缺少的dll,既然你能在vs中运行说明服务器中缺少动态链接库的dll,没有读取动态链接库的环境,注册所有驱动的时候缺少环境,将缺少的相关dll拷贝到c/windows/system32文件夹下,缺少的dll你可以在你的电脑上找到 C:Program Files (x86)Microsoft Visual Studio 10.0VC edistx86Microsoft.VC100.CRT。
这样在运行的时候就不会出错了。如果你还有什么问题也可以在下面留言,有时间我会一一回答的。
原文地址:https://www.cnblogs.com/xiabuyanyu/p/5549971.html