采用ISO8211封装的S57数据,中文读取时乱码及丢字原因分析与解决方法

    很多GIS爱好者或ECDIS开发商在读取S57数据文件时多参考了“ISO8211lib is a C++ library for reading ISO8211-formatted files, such as SDTS and S-57 format “,S57数据NATF字段采用Unicode双字节编码国家属性字段,也就是说S57数据中只有NATF字段的解析与处理涉及了双字节数据问题,特别是NATF字段是可变长度字段,而在

ISO8211.lib

DDFSubfieldDefn::GetDataLength( const char * pachSourceData, int nMaxBytes, int * pnConsumedBytes )

在处理数据长度时最初只考虑了单字节定界符 UT = 31,FT = 30,而将双字节数据当成一种错误数据处理,参考

     /* We only check for the field terminator because of some buggy 
         * datasets with missing format terminators.  However, we have found
         * the field terminator is a legal character within the fields of
         * some extended datasets (such as JP34NC94.000).  So we don't check
         * for the field terminator if the field appears to be multi-byte
         * which we established by the first character being out of the 
         * ASCII printable range (32-127). 
         */

这样会造成测算出的字段长度不正确,因为双字节的字串中的个别字节很可能会出现与定界符冲突,造成数据长度错误,产生丢字问题!考虑到S57规定双字节单元定界符为(0/0) (1/15),字段定界符为(0/0)(1/14)  参见S57 3.10,实际让就是00,1F和00,1E,但在比较时,还要注意系统采用的是小尾序还是大尾序,我使用的系统环境是WINDOWS,大尾序,因此应对上述数据长度测量函数进行修改:

int DDFSubfieldDefn::GetDataLength( const char * pachSourceData,
                                    int nMaxBytes, int * pnConsumedBytes )


{
    if( !bIsVariable ) // 如果数据字段是定长字段
    {
        if( nFormatWidth > nMaxBytes )
        {
            CPLError( CE_Warning, CPLE_AppDefined, 
                      "Only %d bytes available for subfield %s with\n"
                      "format string %s ... returning shortened data.",
                      nMaxBytes, pszName, pszFormatString );


            if( pnConsumedBytes != NULL )
                *pnConsumedBytes = nMaxBytes;


            return nMaxBytes;
        }
        else
        {
            if( pnConsumedBytes != NULL )
                *pnConsumedBytes = nFormatWidth;


            return nFormatWidth;
        }
    }
    else   // 数据字段为变长字段
    {
        int     nLength = 0;
        int     bCheckFieldTerminator = TRUE;


        /* We only check for the field terminator because of some buggy 
         * datasets with missing format terminators.  However, we have found
         * the field terminator is a legal character within the fields of
         * some extended datasets (such as JP34NC94.000).  So we don't check
         * for the field terminator if the field appears to be multi-byte
         * which we established by the first character being out of the 
         * ASCII printable range (32-127). 
         */


        if( pachSourceData[0] < 32 || pachSourceData[0] >= 127 )    // 如果第一个字符为不可见字符,则认为数据为双字节字符集,不检查字段定界符

           bCheckFieldTerminator = FALSE;
        
        while( nLength < nMaxBytes
               && pachSourceData[nLength] != chFormatDelimeter )
        {
               if( bCheckFieldTerminator 
                         && pachSourceData[nLength] == DDF_FIELD_TERMINATOR )
                break;
            nLength++;
        }


        if( pnConsumedBytes != NULL )
        {
            if( nMaxBytes == 0 )
                *pnConsumedBytes = nLength;
            else
                *pnConsumedBytes = nLength+1;
        }
        
        return nLength;
    }

笔者认为可以这样解决(程序上文不变)

        if( pachSourceData[0] < 32 || pachSourceData[0] >= 127 ) 
           bCheckFieldTerminator = FALSE;
        
        while( nLength < nMaxBytes)
        {

               if( bCheckFieldTerminator)

{

if(pachSourceData[nLength] == chFormatDelimeter) 

break;

}

               else

{

if(pachSourceData[nLength] == chFormatDelimeter  && pachSourceData[nLength+1] == 0 )

 break;

}

if(pachSourceData[nLength] == DDF_FIELD_TERMINATOR && pachSourceData[nLength+1] ) break;
           nLength++;
       }


        if( pnConsumedBytes != NULL )
        {
            if( nMaxBytes == 0 )
                *pnConsumedBytes = nLength;
            else

              *pnConsumedBytes = nLength+1;

        }    

        return nLength;
    }

实践中很好的解决了问题

第二个问题,汉字乱码

在后面的数据处理时,由于中文操作系统的汉字一般采用GB18030,也就是GBK编码,因此,在显示这些汉字时还要将NATF字段转成GBK

可以直接使用系统的转换函数:

int len = WideCharToMultiByte(54936,0,(LPCWSTR )tmpStr,m_strLength/2,tmpStr1,m_strLength,0,0);

其中54936是GB18030的CodePage代码

其实第一个问题是在处理汉字乱码问题时发现的,原来只考虑了汉字编码转换问题,而且第二个问题解决后,丢字问题才在一个偶然的时候发现,这个问题在一些商用ECDIS上也存在。

以上浅见,请大师们指正。

 


### 解决方案概述 `java.lang.UnsatisfiedLinkError` 错误通常表示 Java 虚拟机无法找到指定的本地库文件。对于 OpenCV 的情况,该错误可能由以下几个原因引起:缺少必要的本地库文件、路径配置不正确或版本冲突。 以下是针对 `opencv_java455` 加载失败的具体分析和解决方案: --- #### 1. **确认本地库是否存在** 确保目标机器上已安装对应版本的 OpenCV 并且其动态链接库(如 `.dll`, `.so`, 或 `.dylib` 文件)存在于系统的 `java.library.path` 中[^1]。如果未下载对应的二进制文件,则需先完成安装。 可以通过以下命令验证环境变量设置是否正确: ```bash echo %PATH% # Windows 系统下查看 PATH 变量 echo $LD_LIBRARY_PATH # Linux/MacOS 下查看 LD_LIBRARY_PATH 变量 ``` 若发现缺失,请手动添加包含所需共享对象的位置到上述环境中去。 --- #### 2. **调整 Maven 配置引入合适依赖项** 采用推荐方式通过 Maven 构建工具来管理项目所需的外部资源可以有效减少兼容性和维护上的麻烦。下面给出一段适合当前需求的 POM.xml 片段用于拉取最新版支持跨平台操作的 OpenCV 库及其关联组件[^2]: ```xml <dependencies> <!-- 引入 Bytedeco 提供的支持多架构预编译好的 OpenCV --> <dependency> <groupId>org.bytedeco</groupId> <artifactId>opencv-platform</artifactId> <version>4.5.5-1.5.8</version> <!-- 这里选用问题匹配的版本号 --> </dependency> </dependencies> ``` 注意替换 `<version>` 值为实际使用的具体标签名以适配不同场景下的功能特性差异。 随后,在静态初始化块中调用专用类加载器替代原始方法实现自动探测并映射至正确的底层实现逻辑之上: ```java static { Loader.load(org.bytedeco.opencv.global.opencv_core.class); } ``` 此做法不仅简化了传统意义上繁琐的手动干预过程而且增强了程序可移植性表现力强于单纯依靠硬编码形式指明特定名称符串的方式。 --- #### 3. **调试排查技巧** 当遇到此类异常,可通过打印日志进一步定位确切发生位置以及潜在影响因素。例如增加如下代码片段辅助诊断问题根源所在之处: ```java System.out.println("Java Library Path: " + System.getProperty("java.library.path")); try{ Class.forName("org.bytedeco.opencv.presets.opencv_core"); }catch(Throwable t){ t.printStackTrace(); } ``` 以上脚本会输出 JVM 当前搜索范围列表同尝试反射实例化关键类别从而暴露出隐藏细节方便后续处理决策制定依据更加充分可靠些。 --- ### 总结 综上所述,要成功解决因 `UnsatisfiedLinkError` 引发的 OpenCV 动态连接库加载失败现象可以从三个方面入手考虑——核实物理存储介质状态;优化软件供应链结构设计思路转向现代化自动化手段寻求帮助最后辅以科学有效的测试机制保障整体流程顺畅运行无阻塞点存在即可达成预期效果目标。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值