采用ISO8211封装的S57数据,中文读取时乱码及丢字原因分析与解决方法,终极解决方案.
2017-10-08 18:10
751 查看
// 该程序自动判断输入数据的类型,正确返回数据长度,首先判断字段定长或变长,然后根据数据的定界符判断数据是双字节还是字节字串。最后正确返加字串的长度和字段占用内存的长度。
// 依据:
// 字段和子字段终止
// 可变长度子字段必须由“单元定界符”(UT)终止。 可变长度子字段是在数据结构中通过没有范围的格式指示器指定(见第7.2.2.1节)。
// 所有S-57(ISO / IEC 8211数据字段)必须由“字段定界符”(FT)终止。当S-57字段使用不同字符集时时,UT和FT必须编码为该字段指定的级别。
// 下表定义了每个级别的定界符。
// 词汇级 UT FT
// 0级 (1/15)(1/14)
// 1级 (1/15)(1/14)
// 2级 (0/0)(1/15)(0/0)(1/14)
// 当词汇级为2级时,s57允许NATF(国家属性字段)使用本国语言,并用双字节UNICODE编码,单元结束符和字段结束符为两个字节
// 由于编码采用大尾序,因此实际定界符编码为UT(1F00),FT(1E00)
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 nConsumedBytes = 0;
bool bDoubleBytes = FALSE;// 双字节标志
while(nLength + 1 < nMaxBytes)// 循环测试,判断是否为双字节字段
{
if(pachSourceData[nLength] == DDF_UNIT_TERMINATOR && pachSourceData[nLength+1] == 0 ||
pachSourceData[nLength] == DDF_FIELD_TERMINATOR && pachSourceData[nLength] == 0)
{
bDoubleBytes = TRUE;
break;
}
nLength++;
}
nLength = 0; // 字节长度清零
if (bDoubleBytes)
{ // 双字节
while(nLength < nMaxBytes)
{
//双字节单元结束符和字段结束符
if( pachSourceData[nLength] == DDF_UNIT_TERMINATOR && pachSourceData[nLength+1] == 0 &&
pachSourceData[nLength + 2] == DDF_FIELD_TERMINATOR && pachSourceData[nLength+3] == 0)
{
nConsumedBytes = nLength + 4;
break;
}
//双字节单元结束符或字段结束符
if( pachSourceData[nLength] == DDF_UNIT_TERMINATOR && pachSourceData[nLength+1] == 0 ||
pachSourceData[nLength] == DDF_FIELD_TERMINATOR && pachSourceData[nLength+1] == 0)
{
nConsumedBytes = nLength + 2;
break;
}
nLength ++;
}
}
else
{ //单字节
while(nLength < nMaxBytes)
{
//单字节单元结束符和字段结束符
if( pachSourceData[nLength] == DDF_UNIT_TERMINATOR &&
pachSourceData[nLength+1] == DDF_FIELD_TERMINATOR)
{
nConsumedBytes = nLength + 2;
break;
}
//单字节单元结束符或字段结束符
if( pachSourceData[nLength] == DDF_UNIT_TERMINATOR||
pachSourceData[nLength] == DDF_FIELD_TERMINATOR)
{
nConsumedBytes = nLength + 1;
break;
}
nLength++;
}
}
if( pnConsumedBytes != NULL )
{
if( nMaxBytes < nConsumedBytes )
*pnConsumedBytes = nLength;
else
*pnConsumedBytes = nConsumedBytes;
}
return nLength;
}
}
// 依据:
// 字段和子字段终止
// 可变长度子字段必须由“单元定界符”(UT)终止。 可变长度子字段是在数据结构中通过没有范围的格式指示器指定(见第7.2.2.1节)。
// 所有S-57(ISO / IEC 8211数据字段)必须由“字段定界符”(FT)终止。当S-57字段使用不同字符集时时,UT和FT必须编码为该字段指定的级别。
// 下表定义了每个级别的定界符。
// 词汇级 UT FT
// 0级 (1/15)(1/14)
// 1级 (1/15)(1/14)
// 2级 (0/0)(1/15)(0/0)(1/14)
// 当词汇级为2级时,s57允许NATF(国家属性字段)使用本国语言,并用双字节UNICODE编码,单元结束符和字段结束符为两个字节
// 由于编码采用大尾序,因此实际定界符编码为UT(1F00),FT(1E00)
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 nConsumedBytes = 0;
bool bDoubleBytes = FALSE;// 双字节标志
while(nLength + 1 < nMaxBytes)// 循环测试,判断是否为双字节字段
{
if(pachSourceData[nLength] == DDF_UNIT_TERMINATOR && pachSourceData[nLength+1] == 0 ||
pachSourceData[nLength] == DDF_FIELD_TERMINATOR && pachSourceData[nLength] == 0)
{
bDoubleBytes = TRUE;
break;
}
nLength++;
}
nLength = 0; // 字节长度清零
if (bDoubleBytes)
{ // 双字节
while(nLength < nMaxBytes)
{
//双字节单元结束符和字段结束符
if( pachSourceData[nLength] == DDF_UNIT_TERMINATOR && pachSourceData[nLength+1] == 0 &&
pachSourceData[nLength + 2] == DDF_FIELD_TERMINATOR && pachSourceData[nLength+3] == 0)
{
nConsumedBytes = nLength + 4;
break;
}
//双字节单元结束符或字段结束符
if( pachSourceData[nLength] == DDF_UNIT_TERMINATOR && pachSourceData[nLength+1] == 0 ||
pachSourceData[nLength] == DDF_FIELD_TERMINATOR && pachSourceData[nLength+1] == 0)
{
nConsumedBytes = nLength + 2;
break;
}
nLength ++;
}
}
else
{ //单字节
while(nLength < nMaxBytes)
{
//单字节单元结束符和字段结束符
if( pachSourceData[nLength] == DDF_UNIT_TERMINATOR &&
pachSourceData[nLength+1] == DDF_FIELD_TERMINATOR)
{
nConsumedBytes = nLength + 2;
break;
}
//单字节单元结束符或字段结束符
if( pachSourceData[nLength] == DDF_UNIT_TERMINATOR||
pachSourceData[nLength] == DDF_FIELD_TERMINATOR)
{
nConsumedBytes = nLength + 1;
break;
}
nLength++;
}
}
if( pnConsumedBytes != NULL )
{
if( nMaxBytes < nConsumedBytes )
*pnConsumedBytes = nLength;
else
*pnConsumedBytes = nConsumedBytes;
}
return nLength;
}
}
相关文章推荐
- 采用ISO8211封装的S57数据,中文读取时乱码及丢字原因分析与解决方法
- 采用ISO8211封装的S57数据,中文读取时乱码及丢字原因分析与解决方法-更正与补充
- MySQL字符集中文乱码终极解决方案和mysql查询中文问题解决方法[转贴]
- Code:Blocks 中文乱码问题原因分析和解决方法!
- MySQL字符集中文乱码终极解决方案和mysql查询中文问题解决方法[转贴]
- Request读取中文数据乱码的原因,以及解决办法
- MySQL字符集中文乱码终极解决方案和mysql查询中文问题解决方法[转贴]
- 解决方法:ASP读取数据库中的中文数据出现乱码的问题
- Code:Blocks 中文乱码问题原因分析和解决方法!
- MySQL字符集中文乱码终极解决方案和mysql查询中文问题解决方法[转贴]
- MySQL字符集中文乱码终极解决方案和mysql查询中文问题解决方法[转贴]
- Code:Blocks 中文乱码问题原因分析和解决方法
- php读取mysql中文数据出现乱码的解决方法
- Codeblocks 中文乱码问题原因分析和解决方法!
- Code:Blocks 中文乱码问题原因分析和解决方法!
- php读取mysql中文数据出现乱码的解决方法
- 关于htmlparsr在显示繁体中文时出现乱码的原因分析和解决方法
- R 从mysql读取数据中文乱码的解决方法
- Code::Blocks 中文乱码问题原因分析和解决方法
- MySQL字符集中文乱码终极解决方案和mysql查询中文问题解决方法[转贴]