GDAL打开mdb文件失败解决方法(二)
2017-02-17 13:30
323 查看
上一篇http://blog.csdn.net/liminlu0314/article/details/53433014博文中说到,可以通过配置项来解决mdb文件打开失败的问题。该问题主要是在64位的程序中会出现。仔细查看gdal的代码,发现在源码中已经针对这个问题进行了修改,但是测试发现修改的不彻底。
具体的bug信息参考http://trac.osgeo.org/gdal/ticket/5594。GDAL库中源码片段如下,详见文件ogrodbcdatasource.cpp中的132行左右,位于函数OGRODBCDataSource::OpenMDB中。
/* -------------------------------------------------------------------- */
/* Initialize based on the DSN. */
/* -------------------------------------------------------------------- */
CPLDebug( "ODBC", "EstablishSession(%s)", pszDSN );
if( !oSession.EstablishSession( pszDSN, NULL, NULL ) )
{
int bError = TRUE;
if( EQUAL(pszDSN, "") )//注释掉这句话即可
{
// Trying with another template (#5594)
pszDSNStringTemplate = "DRIVER=Microsoft Access Driver (*.mdb, *.accdb);DBQ=%s";
CPLFree( pszDSN );
pszDSN = (char *) CPLMalloc(strlen(pszNewName)+strlen(pszDSNStringTemplate)+100);
snprintf( pszDSN,
strlen(pszNewName)+strlen(pszDSNStringTemplate)+100,
pszDSNStringTemplate, pszNewName );
CPLDebug( "ODBC", "EstablishSession(%s)", pszDSN );
if( oSession.EstablishSession( pszDSN, NULL, NULL ) )
{
bError = FALSE;
}
}
if( bError )
{
CPLError( CE_Failure, CPLE_AppDefined,
"Unable to initialize ODBC connection to DSN for %s,\n"
"%s", pszDSN, oSession.GetLastError() );
CPLFree( pszDSN );
return FALSE;
}
}
上述代码虽然加了匹配另一个模板,但是有个判断if( EQUAL(pszDSN, "") ),这个判断由于pszDSN通过上面的赋值,肯定是有值的,所以这个判断永远为FALSE,也就是if内的代码不会执行,这样就导致修改了其实和没有修改是一样的。所以为了能够在使用第一个模板失败时,使用第二个模板,需要将if这句话注释掉即可。
修改完重新编译即可。
PS:最后又发现了一个问题,在打开调试开关之后,执行会崩溃,通过调试发现位于该文件的218行的 if( oTableList.GetTables() )中执行失败,函数GetTables的源码如下:
int CPLODBCStatement::GetTables( const char *pszCatalog,
const char *pszSchema )
{
CPLDebug( "ODBC", "CatalogNameL: %s\nSchema name: %s",
pszCatalog , pszSchema); //这句出问题了
#if (ODBCVER >= 0x0300)
if( !m_poSession->IsInTransaction() )
{
// Commit pending transactions and set to autocommit mode.
m_poSession->ClearTransaction();
}
#endif
......
调试发现在调用CPLDebug函数时,传入的两个参数均为NULL导致CPLDebug函数崩溃,此处加一个判断就可以了。如果不启用调试应该也不会出问题。
具体的bug信息参考http://trac.osgeo.org/gdal/ticket/5594。GDAL库中源码片段如下,详见文件ogrodbcdatasource.cpp中的132行左右,位于函数OGRODBCDataSource::OpenMDB中。
/* -------------------------------------------------------------------- */
/* Initialize based on the DSN. */
/* -------------------------------------------------------------------- */
CPLDebug( "ODBC", "EstablishSession(%s)", pszDSN );
if( !oSession.EstablishSession( pszDSN, NULL, NULL ) )
{
int bError = TRUE;
if( EQUAL(pszDSN, "") )//注释掉这句话即可
{
// Trying with another template (#5594)
pszDSNStringTemplate = "DRIVER=Microsoft Access Driver (*.mdb, *.accdb);DBQ=%s";
CPLFree( pszDSN );
pszDSN = (char *) CPLMalloc(strlen(pszNewName)+strlen(pszDSNStringTemplate)+100);
snprintf( pszDSN,
strlen(pszNewName)+strlen(pszDSNStringTemplate)+100,
pszDSNStringTemplate, pszNewName );
CPLDebug( "ODBC", "EstablishSession(%s)", pszDSN );
if( oSession.EstablishSession( pszDSN, NULL, NULL ) )
{
bError = FALSE;
}
}
if( bError )
{
CPLError( CE_Failure, CPLE_AppDefined,
"Unable to initialize ODBC connection to DSN for %s,\n"
"%s", pszDSN, oSession.GetLastError() );
CPLFree( pszDSN );
return FALSE;
}
}
上述代码虽然加了匹配另一个模板,但是有个判断if( EQUAL(pszDSN, "") ),这个判断由于pszDSN通过上面的赋值,肯定是有值的,所以这个判断永远为FALSE,也就是if内的代码不会执行,这样就导致修改了其实和没有修改是一样的。所以为了能够在使用第一个模板失败时,使用第二个模板,需要将if这句话注释掉即可。
修改完重新编译即可。
PS:最后又发现了一个问题,在打开调试开关之后,执行会崩溃,通过调试发现位于该文件的218行的 if( oTableList.GetTables() )中执行失败,函数GetTables的源码如下:
int CPLODBCStatement::GetTables( const char *pszCatalog,
const char *pszSchema )
{
CPLDebug( "ODBC", "CatalogNameL: %s\nSchema name: %s",
pszCatalog , pszSchema); //这句出问题了
#if (ODBCVER >= 0x0300)
if( !m_poSession->IsInTransaction() )
{
// Commit pending transactions and set to autocommit mode.
m_poSession->ClearTransaction();
}
#endif
......
调试发现在调用CPLDebug函数时,传入的两个参数均为NULL导致CPLDebug函数崩溃,此处加一个判断就可以了。如果不启用调试应该也不会出问题。
相关文章推荐
- GDAL打开mdb文件失败解决方法
- GDAL打开mdb文件失败解决方法
- ifstream或ofstream打开带有中文路径的文件失败解决方法
- vs2015打开cshtml文件失败的解决方法
- VS 属性和资源文件打开失败的解决方法
- VC6.0下打开文件失败的解决方法
- SQL Server 2008附加数据库失败:无法打开物理文件拒绝访问解决方法
- .oracle文件缺失导致打开失败的解决方法
- 附加自动命名的数据库,但失败。已存在同名的数据库,或指定的文件无法打开或位于 UNC 共享目录中[解决方法]
- VC6.0下打开文件失败的解决方法
- word2010打开97-03格式的word文件失败的解决方法
- Oracle打开数据库文件失败的解决方法
- 附加自动命名的数据库,但失败。已存在同名的数据库,或指定的文件无法打开或位于 UNC 共享目录中[解决方法]
- 附加自动命名的数据库 但失败。已存在同名的数据库 或指定的文件无法打开或位于 unc 共享目录中。【解决方法】
- 关于Sql Server企业管理器MMC 不能打开文件的解决方法
- 用ASP打开远端MDB文件的方法
- 英文Windows无法打开中文名CHM文件的解决方法
- 用ASP打开远端MDB文件的方法
- 用ASP打开远端MDB文件的方法
- 打开CHM文件出现错误的解决方法