学习open62541 --- [31] 正确显示中文字符

本文主要讲述在win10下如何正确的显示中文字符,开发环境是VS2015


一 Server端代码

// server.cpp

/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
* See http://creativecommons.org/publicdomain/zero/1.0/ for more information. */

#include <signal.h>
#include <stdlib.h>

#include "open62541.h"

UA_Boolean running = true;

static void stopHandler(int sign) {
    
    
	UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "received ctrl-c");
	running = false;
}



static void addVariable(UA_Server *server)
{
    
    
	/* Define the attribute of the myInteger variable node */
	UA_VariableAttributes attr = UA_VariableAttributes_default;


	UA_LocalizedText orig = UA_LOCALIZEDTEXT((char*)"zh-CN", "123你456");

	UA_Variant_setScalar(&attr.value, &orig, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
	attr.description = UA_LOCALIZEDTEXT("en-US", "info");
	attr.displayName = UA_LOCALIZEDTEXT("en-US", "info");
	attr.dataType = UA_TYPES[UA_TYPES_LOCALIZEDTEXT].typeId;
	attr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;

	/* Add the variable node to the information model */
	UA_NodeId myNodeId = UA_NODEID_STRING(1, "info");
	UA_QualifiedName myName = UA_QUALIFIEDNAME(1, "info");
	UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
	UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES);
	UA_Server_addVariableNode(server, myNodeId, parentNodeId, parentReferenceNodeId, myName,
			UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), attr, NULL, NULL);
}


static void ctrlCallback(UA_Server *server, void *data)
{
    
    
	UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "ctrl callback");

	UA_Variant val;
	UA_Server_readValue(server, UA_NODEID_STRING(1, "info"), &val);

	UA_LocalizedText *pOrig = (UA_LocalizedText*)(val.data);
	
	for (unsigned int i = 0; i < pOrig->text.length; ++i)
	{
    
    
		printf("0x%x ", pOrig->text.data[i]);
	}
	printf("\n%.*s\n\n", pOrig->text.length, pOrig->text.data);

}


int main(void)
{
    
    
	signal(SIGINT, stopHandler);
	signal(SIGTERM, stopHandler);

	UA_Server *server = UA_Server_new();
	UA_ServerConfig_setDefault(UA_Server_getConfig(server));

	addVariable(server);

	UA_Server_addRepeatedCallback(server, ctrlCallback, NULL, 2000, NULL); // call every 2s

	UA_StatusCode retval = UA_Server_run(server, &running);

	UA_Server_delete(server);

	return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;
}

代码功能比较简单,主要是添加一个变量,变量值是“123你456”,然后每隔2秒去读其值,最后打印出来。

运行后使用UaExpert连接,显示乱码,
在这里插入图片描述
但是却可以在UaExpert这边手动修改成正确的中文,修改成正确的“123你456”后,查看server端的定时打印,
在这里插入图片描述
第一处红色标记的是修改前的值,可以看到“你”对应的16进制值是0xc4 0xe3,第二处红色标记的是修改后的值,“你”对应的16进制值却是0xe4 0xbd 0xa0,这是怎么回事呢?


二 解决问题

经过网上查找资料得知:根本原因是两边的编解码方式不同造成的。server这边dos终端使用的是GB18030编码方式(也可能是别的),而UaExpert这边使用的是UTF-8编码方式。

这种对于英文没有问题,但是对于中文却不那么友好。

知道了原因,解决起来就比较简单了,有2种方式:

1. 使用wstring (要求至少C++11)

如果是用c++进行开发,且c++版本是11及以上,那么就可以使用wstring,如下,

#include <string>
#include <locale>
#include <codecvt>

static std::string wstringToUtf8(const std::wstring& str)
{
    
    
	std::wstring_convert<std::codecvt_utf8<wchar_t> > strCnv;
	return strCnv.to_bytes(str);
}

static void addVariable(UA_Server *server)
{
    
    
	/* Define the attribute of the myInteger variable node */
	UA_VariableAttributes attr = UA_VariableAttributes_default;

	std::wstring textStr = L"123你456";
	std::string temp = wstringToUtf8(textStr);

	UA_LocalizedText orig = UA_LOCALIZEDTEXT((char*)"zh-CN", (char*)(temp.c_str()));

	UA_Variant_setScalar(&attr.value, &orig, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
	attr.description = UA_LOCALIZEDTEXT("en-US", "info");
	attr.displayName = UA_LOCALIZEDTEXT("en-US", "info");
	attr.dataType = UA_TYPES[UA_TYPES_LOCALIZEDTEXT].typeId;
	attr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;

	/* Add the variable node to the information model */
	UA_NodeId myNodeId = UA_NODEID_STRING(1, "info");
	UA_QualifiedName myName = UA_QUALIFIEDNAME(1, "info");
	UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
	UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES);
	UA_Server_addVariableNode(server, myNodeId, parentNodeId, parentReferenceNodeId, myName,
			UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), attr, NULL, NULL);
}

添加对应头文件和函数wstringToUtf8(),然后在addVariable()里调用wstringToUtf8(),这样在UaExpert这边就可以正确显式中文了。

2. 修改dos终端编码方式

这种方式比较麻烦,本人参考了这篇文章把dos终端的编码方式改成UTF-8。

注意:改完后Visual Studio中源码中的中文字符变成了乱码,需要重新写一遍,最后再重新编译运行,此时再使用UaExpert进行连接,就可以正确显式中文了。

在这里插入图片描述


三 总结

本文主要讲述在Win下如何正确显式中文字符,推荐使用UTF-8编码方式。

猜你喜欢

转载自blog.csdn.net/whahu1989/article/details/106628606