记上报信息格式异常问题的解决

news/2024/10/18 14:00:44

本文记述解决上报信息格式异常问题的全过程。

问题描述

生产环境监控上报无法解析终端信息,通过日志发现是PCN字段前面缺失#号,导致解析程序解析失败。正常情况下,应该展示如下内容:

HD1234#PCN1234

发生错误情况时,记录如下

HD123?PCN1234

问题分析以及解决

通过进一步的后台日志数据分析,发现上述异常情况发生在特定终端,这说明是因为某些终端存在特殊情况,程序中没有考虑到这类特殊情况,从而导致的问题。HD字段后面跟着的是硬盘序列号,PCN字段后面是主机名称,他们中间用 # 字符连接。

下一步是复现问题,复现思路为在本地尝试构造特殊数据,并在复现这类情况,具体做法是在HD~123的后面手动追加异常数据,再和后面正常的 #PCN~1234进行拼接,用程序来检测拼接后是否出现?字符。

由于不知道什么数据会触发,怀疑是混入了无效中文导致的,于是,复习了下中文编码的知识后,

中文编码ASCII --》 GB2312 			--》GBK          --》GB18030体系(字符集+编码格式统一)1980年发布          1995年发布          2000年发布 GB18030-2000  2005年发布 GB18030-20056763个汉字和符号     2万多个字符          7万多字符定长2字节		    汉字2字节           变长多字节字符集(1\2\4字节组成)英文1字节		   大部分中文字符只需要2个字节单字节ASCIIASCII -->										Unicode编码体系(规定字符集)编码的存储和解析有 UTF8、UTF16等标准。通过UTF8编码的中文,需要3个字节如果一个字节最高位是0,说明该字节为ASCII码,查表解析即可,否则认为是多字节编码,需要联合下一个字节一起解析。
utf8编码与ASCII完全兼容,最高位1的数量表示当前字符占用的字节数。对于汉字来说,没有半角全角的区分;对于符号来说,ASCII和GB2312的符号编码不同,表现不同,GB2312编码的为全角,ASCII编码的为半角。对于ASCII来说,它是7位编码,共128个字符,分为95个可打印字符和33个不可打印字符,可打印字符用于显示在输出设备,如屏幕或打印纸;不可打印字符又称为控制字符,编码范围在 0x00~0x1F 之间,用于向计算机发出控制指令。找了几个特例汉字,
GB2312没有,GBK没有,GB18030中独有的字:㙍 0x8230AB33
GB2312没有,GBK有的字: 掆 0x92E2  昞 0x955C 鐯 0xE840 淂 0x9BFA

输入GB2312没有,GBK有的字,能够正常展示;
输入GB2312没有,GBK没有,GB18030中独有的字,显示为 HD~??#PCN,无法显示,但后面的#号没丢。

输入中文的尝试不行,干脆从0~255都试一遍,从1个字节,到2个字节,再到3个字节,都循环一把。这个流程的关键在于如何检测到异常。

判断异常有两个方向,一个是判断是否出现?,另一个是判断是否缺少#。

判断是否出现?, 尝试用 Find 函数查找,几轮全部循环完了都找不到,奇了怪了。

判断是否缺少#,用这个方法可以找到,问题是有太多字符组合发生这种情况了,太多的报错信息反倒是让我怀疑是这个思路不对。在随后的分析中,找一两个错误字符组合一试,果然会出现异常情况,随后多次测试,直到确定发生异常的最佳情况,下面以简化程序为例子来说明:

// 尝试处理无效字符串连接时的问题
void test_invalid_character_string_strcat()
{char sz2[32] = "123";const int nBufSize = 256;char szBuf[nBufSize] = { 0 };char sz1[32] = { 0x31, 0x13 };	// 测试各种不可打印字符包含在最后时,对后面格式化内容的影响//char sz1[32] = { 0x31, 0x01, 0x31 };	// 测试各种不可打印字符包含在中间时,对后面格式化内容的影响
#if 1for (char i = 0;i < 0x1F; i++){sz1[1] = i;sz1[2] = 0;memset(szBuf, 0, nBufSize);_snprintf_s(szBuf, nBufSize, nBufSize - 1, "sz1:%s#sz2:%s", sz1, sz2);printf("0x%x:%c szBuf:(%s) \t", i, i, szBuf);if (i % 2 == 1){printf("\n");fflush(nullptr);}}printf("\n");
#endif//char sz1[32] = { 0x30, 0x92 };	    // 无效字符包含在最后,会吞掉后面的1个符号//char sz1[32] = { 0x30, 0x91, 0x30 };	// 无效字符包含在中间,不会吞掉后面的1个符号//char sz1[32] = { 0x30, 0x01 };	    // 不可打印字符包含在最后,有些字符会会吞掉后面1个字符内容//char sz1[32] = { 0x30, 0x06 ,0x30};	// 不可打印字符包含在中间,_snprintf_s(szBuf, nBufSize, nBufSize - 1, "sz1:%s#sz2:%s", sz1, sz2);cout << "szBuf:" << szBuf << endl;string strTest(szBuf);int nIdx = strTest.find('?');//assert(nIdx == -1);		// 当格式化异常时,界面上展示的是?,但内存中是对应的0x91解决了当异常出现时,无法用 find 来定位int nFind = '?';char* pRet = strchr(szBuf, nFind);//assert(pRet == nullptr);getchar();exit(0);
}

经过上述代码实测,得出以下结论:

当待连接字符串中包含无效字符或不可打印字符时,在格式化时会影响后面的内容,具体表现为:

当出现不可打印字符时,详细影响情况见下图:

image.png

当不可见字符为0x0,0x7,0x8,0x9,0xa等字符时,后面的内容不会被影响,为其他不可打印字符时,在显示时,会吃掉后面的1个字符
比如 0x11 0x35, 会显示为左三角; 当为 0x11 0x35 0x35, 会显示为左三角5;这说明不可见字符在显示时会隐藏掉后一个字符。

当出现无效字符(字符数值大于127的)时,无效字符在字符串中间,不会影响后续格式化;在字符串最后时,会吞掉后面的一个字符,自身显示为?

小结

定位到问题原因,解决方案也就出来了。检测待格式化字符串,如果发现最后1位为无效字符,则在它后面追加一个有效字符,可确保不会影响后续格式化内容。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/73043.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

云存储图片生成缩略图开发

作者:狼哥 团队:坚果派 团队介绍:坚果派由坚果等人创建,团队拥有12个华为HDE带领热爱HarmonyOS/OpenHarmony的开发者,以及若干其他领域的三十余位万粉博主运营。专注于分享HarmonyOS/OpenHarmony、ArkUI-X、元服务、仓颉。团队成员聚集在北京,上海,南京,深圳,广州,宁…

PHP简介与开发环境搭建

PHP简介与开发环境搭建 一、PHP简介 PHP,全称PHP: Hypertext Preprocessor(超文本预处理器),是一种广泛使用的开源服务器端脚本语言,尤其适合Web开发。PHP由Rasmus Lerdorf在1994年创建,最初是为了维护个人网页而制作的简单程序,后来逐渐发展成为功能强大的脚本语言。PH…

2153: 【例8.3】计算球的体积 球的体积公式

include <bits/stdc++.h> using namespace std; double r, pi=3.14; int main( ) { cin >> r; cout << fixed << setprecision(2)<< 4.0/3.0pirrr; return 0; } 球体是一个半圆绕直径所在直线旋转一周所成的空间几何体,简称球。球体是有且只有一…

深入理解浮点数的运算

浮点数的运算步骤 浮点数的加减运算一般由以下五个步骤完成:对阶、尾数运算、规格化、舍入处理、溢出判断 所谓对阶是指将两个进行运算的浮点数的阶码对齐的操作。对阶的目的是为使两个浮点数的尾数能够进行加减运算。因为,当进行 $ M_{x} \times 2^{E_{x}}$与 $ M_{y} \time…

轻松上手-识图文字朗读

作者:狼哥 团队:坚果派 团队介绍:坚果派由坚果等人创建,团队拥有12个华为HDE带领热爱HarmonyOS/OpenHarmony的开发者,以及若干其他领域的三十余位万粉博主运营。专注于分享HarmonyOS/OpenHarmony、ArkUI-X、元服务、仓颉。团队成员聚集在北京,上海,南京,深圳,广州,宁…

mysql语法-DMLDQL

1.DML操作数据——添加、修改、删除 (1)添加数据:实例(2)修改数据实例注意:修改时如果update语句不加where条件,则会把表中所有数据都修改了! (3)删除数据:实例2.DQL查询 查询语法(1)基础查询:实例(2)条件查询:

免费使用AI写作助手,为你轻松打造爆款文章

在当今内容为王的时代,一篇高质量的文章能够迅速抓住读者的眼球,提升个人或品牌的曝光度。但对于许多创作者而言,灵感枯竭和写作效率低下是常见的挑战。此时,免费AI写作助手的出现,为解决这些问题提供了新的可能性。以下是这款AI写作助手的独特魅力和使用指南。一、AI写作…

从组合优化问题建模到贪心法求解以简单调度为例

此为课题组所指导本科生和低年级硕士生学习组合优化问题汇报 所用教材:北京大学屈婉玲教授《算法设计与分析》 课程资料:https://www.icourse163.org/course/PKU-1002525003 承诺不用于任何商业用途,仅用于学术交流和分享更多内容请关注课题组官方中文主页:https://JaywayX…