`

多端点传输杜绝乱码方案

阅读更多

多个端点之前传输字符串(String),实际上是传输字节流(Byte[])。如果发送方采用UTF8编码将字符串变为字节流(Byte[]=String.getBytes("UTF8")),当接收方接受到后,却使用GBK来解码字节流到字符串(String = new String(byte[],"GBK");),那么就会出现乱码。为了避免乱码这种情况,通讯双方需要知道对方的编码格式,或者双方统一编码。

 

本文介绍的方式,是无需定编码的方式,来杜绝乱码,原理就是使用UNICODE这个字符集和UTF16编码格式。本方案的驱动来源于实际工作中遇到3个端点之间的通讯需要相互约定编码格式,导致部署时麻烦而且容易乱码。

 

1 对于JAVA发送端,

发送字符串前,先转为UNICODE文本,具体处理如下:

 

    public static String toUnicodeString(String s){
    	StringBuilder strb = new StringBuilder();
    	char[] c = s.toCharArray();
    	for(int i=0,len=c.length;i<len;i++){
	    	if(c[i] < 128){
	    		strb.append(c[i]);
	    	}else{
	    		strb.append("\\u");
	    		String hex = Integer.toHexString(c[i]);
	    		
	    		if(hex.length()<4){
	    			int padLen = 4-hex.length();//需要左补齐的0
	    			for(int k=0;k<padLen;k++){
	    				hex = "0" + hex;
	    			}
	    		}
	    		strb.append(hex);
	    	}
    	}
    	return strb.toString();
    }

上述代码的原理在于,利用JAVA内存中使用UTF16编码保存字符串的特点,将字符串转换为UNICODE文本。

 

这样子,例如

”中文abc"

 通过如下调用

 

String unicodeStr = toUnicodeString("中文abc");
System.out.println(unicodeStr);

 

变成了

\u4e2d\u6587abc

 注意这个最后的字符串,它仅仅包含0-127编码的基本字符,这些字符在所有的编码格式中,解析和被解析都是一致的,不会存在乱码问题。

 

2 对于JAVA接受端,

在使用接受的UNICODE文本字符串之前,先转换为正确的字符串。

 

    /**
     * 将字符的unicode部分,全部转换成具体字符
     * @param s
     * @return
     */
    public static String parseUnicodeString(String s){
    	StringBuilder rtn = new StringBuilder();
    	for(int i=0,len=s.length();i<len;i++){
    		char c = s.charAt(i);
    		if(c=='\\'){
    			i++;
    			char c1 = s.charAt(i);
    			if(c1 == 'u'){
    				try{
    					char c_chinese = (char) Integer.parseInt(s.substring(i+1,i+1+4),16);
    					rtn.append(c_chinese);
    					i += 4;
    				}catch(Exception e){
    					throw new RuntimeException("parseUnicodeString出错",e);
    				}
    			}else{
    				rtn.append(c).append(c1);
    			}
    		}else{
    			rtn.append(c);
    		}
    	}
    	return rtn.toString();
    }

 这样子,例如

 

\u4e2d\u6587abc

 通过如下调用

 

		String s = parseUnicodeString("\u4e2d\u6587abc");
		System.out.println(s);

 

变成了

”中文abc"

 

3 对于C++发送端

 

std::string Util::toUnicodeString(std::string& strascii)  
{   string rtn = "";
    int widesize = MultiByteToWideChar (CP_ACP, 0, (char*)strascii.c_str(), -1, NULL, 0);  
    wchar_t * wcharBuf = new wchar_t[widesize];
    int convresult = MultiByteToWideChar (CP_ACP, 0, (char*)strascii.c_str(), -1, wcharBuf, widesize);
	
	for(int i=0;i<widesize-1;i++){
		if(wcharBuf[i]<128){
			rtn += (char)wcharBuf[i];
		}else{
			char hex[6]={0};
			sprintf(hex,"\\u%04x",wcharBuf[i]);
			rtn += hex;
		}
	}
	
	delete [] wcharBuf;
    return rtn;  
} 

关键在于WIDECHAR,由于JAVA本身在内存的字符串就是用WIDECHAR存放,所以节省了一些步骤,但是C++就没有这个特性,所以需要MultiByteToWideChar来将ANSI转换为UTF16格式,最后存放在WIDECHAR。

 

 

 4 对于C++接收端

 

std::string Util::parseUnicodeString(std::string& strUnicodeFormat)  
{  
	string rtn = "";
	wstring wstr;
	wstr.reserve(strUnicodeFormat.length()*2);
	//将ascii char转换为unicode wchar
	for(int i=0;i<strUnicodeFormat.length();i++){
		char c = strUnicodeFormat[i];
		if('\\' == c){
			i++;
			char c1 = strUnicodeFormat[i];
			if('u'==c1){
				string hex = strUnicodeFormat.substr(i+1,4);
				WCHAR wcs[2];
				memset(wcs,0,sizeof(wcs));
				wcs[0] = (WCHAR)(strtol(hex.c_str(),NULL,16));
				wstr.append(wcs);
				i += 4;
			}else{
				WCHAR wcs[2];
				memset(wcs,0,sizeof(wcs));
				wcs[0] = (WCHAR)c;
				
				WCHAR wcs1[2];
				memset(wcs1,0,sizeof(wcs));
				wcs1[0] = (WCHAR)c1;
				
				wstr.append(wcs).append(wcs1);
			}
		}else{
			WCHAR wcs[2];
			memset(wcs,0,sizeof(wcs));
			wcs[0] = (WCHAR)c;
			wstr.append(wcs);
		}
	}
	return UnicodeToANSI(wstr);
} 

 5 优点与缺点

这种方案的好处就是无需担心文本的乱码问题了,利用了UNICODE,简单可靠。

缺点在于

1. 字符串发送和接受,需要一定程度上的额外处理。

2. 传送的字节流也会有一定程度上的增大。这个可以用GZIP去规避。(C++使用zlib,Java使用GzipOutputStream)。

 

没有完美的方案,好方案是权衡轻重后得出的方案。对于本人来说,该方案带来的效率下降并不大,对比起乱码这种严重又纠结的问题(如果端点很多,程序编码的配置就很要命了),带来的得益要多得多;对于部署人员来说,则减少了部署的工作量和压力,皆大欢喜:)

 

 

1
1
分享到:
评论
3 楼 liushilang 2013-07-08  
好东西,也是一种好的思想
2 楼 lazy_ 2013-07-06  
qlstrike 写道
是个好想法,不知道有没有实际线上练过啊

这是正式生产环境中运行的代码,仅仅有少量的修改
1 楼 qlstrike 2013-07-05  
是个好想法,不知道有没有实际线上练过啊

相关推荐

    EAD端点主动防御解决方案

    【EAD端点主动防御解决方案】是针对当前网络环境中日益严重的安全问题提出的一种创新性防护策略。传统的网络安全方法多依赖于被动防御,即在安全事件发生后进行修复,但这种方式往往无法有效防止威胁的扩散。H3C端点...

    JAVA多线程端点续传下载

    JAVA多线程端点续传下载JAVA多线程端点续传下载JAVA多线程端点续传下载JAVA多线程端点续传下载JAVA多线程端点续传下载JAVA多线程端点续传下载JAVA多线程端点续传下载JAVA多线程端点续传下载JAVA多线程端点续传下载...

    usb2.0端点控制传输

    端点0控制传输详解

    Check Point把间谍软件防御功能整合至其端点安全解决方案

    在互联网安全领域处于全球领先地位的Check Point软件技术有限公司宣布推出一款先进的间谍软件防御方案,它整合了Check Point领先行业的端点安全解决方案。这款整合的产品为客户提供最全面的端点安全,包括在单一客户...

    EAD端点准入防御解决方案介绍.pdf

    EAD方案的基本思路是建立一个多层次的防御体系,通过在端点设备接入网络前进行安全检查和认证。这包括检查操作系统、应用程序、补丁更新状态,以及是否存在恶意软件等。只有当设备满足所有安全要求时,才会允许其接...

    端点准入防御解决方案复习过程.pdf

    【端点准入防御解决方案】是一种综合性的网络安全策略,旨在通过严格控制网络终端的准入,确保所有接入网络的设备都符合企业设定的安全标准。这一解决方案针对当前互联网环境中的各种安全威胁,如病毒、软件漏洞和...

    基于情报的端点安全防护方案介绍.pptx

    介绍MacAfee动态端点威胁防护战略,新一代端点威胁防御解决方案

    H3CEAD端点准入防御组件解决方案.pdf

    H3CEAD端点准入防御组件解决方案.pdfH3CEAD端点准入防御组件解决方案.pdfH3CEAD端点准入防御组件解决方案.pdfH3CEAD端点准入防御组件解决方案.pdfH3CEAD端点准入防御组件解决方案.pdfH3CEAD端点准入防御组件解决方案...

    H3CEAD端点准入防御组件解决方案.docx

    H3CEAD端点准入防御组件解决方案.docxH3CEAD端点准入防御组件解决方案.docxH3CEAD端点准入防御组件解决方案.docxH3CEAD端点准入防御组件解决方案.docxH3CEAD端点准入防御组件解决方案.docxH3CEAD端点准入防御组件...

    USB学习:GD32USB虚拟多串口(F470端点不够)

    对于虚拟多串口,每个串口通常需要至少两个端点(一个IN端点用于发送,一个OUT端点用于接收)。如果GD32F470的端点数量不足以支持所需的串口数量,我们需要采取优化策略: 1. **端点复用**:设计程序时,可以考虑...

    多个字的端点检测

    语音多字的端点检测,找出清浊分界,并以线的形式标出界线

    Symantec 端点安全SEP解决方案

    Symantec™ Endpoint Protection 将 Symantec AntiVirus™ 与高级威胁防御功能相结合,可以为笔记本、台式机和 服务器提供无与伦比的恶意软件防护能力。它甚至可以 防御那些最复杂的攻击,这些攻击能够躲避传统的...

    libusb 块传输 同步传输 例程

    2. bulk.c:这个文件很可能包含了一个或多个示例,展示了如何使用libusb库进行块传输。通过阅读和理解这段代码,你可以学习如何设置USB设备,打开会话,找到正确的端点,设置传输缓冲区,以及如何处理传输结果。 在...

    matlab.rar_双门限法_端点检测_端点检测C_语音端点_语音端点 检测

    通常,时间窗口的大小会影响端点检测的敏感性,较小的窗口可以更精确地定位端点,但可能会引入更多的噪声;较大的窗口可以提供更好的噪声抑制,但可能导致端点定位的延迟。 3. **比较与判断**:如果连续多个时间...

    关于基于情报的端点安全防护方案介绍的分析说明.zip

    基于情报的端点安全防护方案是应对日益复杂和动态的威胁环境的一种策略,它强调利用实时威胁情报来增强对端点的保护。以下是这种方案的详细说明: 1. **威胁情报**:基于情报的端点安全系统依赖于实时的威胁情报,...

    USB 数据传输 块传输、中断传输、同步传输和控制传输

    如果块传输的数据量大于块端点所支持的最大数据包长度,则USB主控制器会将该传输分成多个块事务处理。 - **应用场景**:特别适合于打印机和扫描仪等设备,这些设备要求较高的数据正确性,而对传输速率的要求相对较...

    使用STM32的USB库支持控制端点

    在探讨STM32如何利用其内置的USB库来管理控制端点时,我们需要理解控制端点传输的基本概念。控制端点是USB通信的一个重要组成部分,用于传输控制请求和响应。这些请求通常涉及到设备配置、状态查询等操作。 根据...

    java端点续传

    Java端点续传技术,又称为断点续传,是在文件传输过程中,如果因为网络问题或其他因素中断,可以从上次中断的地方继续传输,而无需重新开始整个过程。这种技术在大文件传输、网络不稳定或者需要节省时间的情况下非常...

    Windows统一端点管理方案.pdf

    Windows统一端点管理方案.pdf

    3_端点检测_

    在实际应用中,端点检测的性能会受到很多因素影响,包括噪声环境、说话人的音量变化、语速等。因此,算法通常需要进行参数优化以适应不同的应用场景。双门限检测法虽然简单易懂,但在某些复杂环境下可能不够精确,...

Global site tag (gtag.js) - Google Analytics