转:https://blog.csdn.net/XIAOZHI0999/article/details/80785570

本文讨论C#同ue4进行通信,出现的中文乱码情况,其他语言类似。

本文分两种情况讨论,

1.C#向ue4发送string

在C#发送string时,要先区分发送的字符串中是否包含中文,判断方法很简单,如下:

private bool IsPureAnsi(string str)
{
for (int i = 0; i < str.Length; ++i)
{
if ((int)str[i] > 127)
{
return false;
}
}

return true;
}
当string中不包含中文时,每个字符占1个字节,string前要先发送string的长度,占4个字节,string结束要加'\0'结尾(c传统)
当string中包含中文时,每个字节占用2个字节,格式同上(注意string长度无需*2,而且string长度要取反,string结尾需要两个字节的'\0')

具体代码如下:

public byte[] StringToBytes(string str)
{
Stream stream = new MemoryStream();

if (this.IsPureAnsi(str))
{
byte[] strLenBytes = System.BitConverter.GetBytes(str.Length + 1);
stream.Write(strLenBytes, 0, strLenBytes.Length);

byte[] strBytes = Encoding.ASCII.GetBytes(str);
stream.Write(strBytes, 0, strBytes.Length);
stream.WriteByte(0);
}
else
{
int strLen = str.Length + 1;
byte[] strLenBytes = System.BitConverter.GetBytes(-strLen);
stream.Write(strLenBytes, 0, strLenBytes.Length);

byte[] strBytes = Encoding.Unicode.GetBytes(str);
stream.Write(strBytes, 0, strBytes.Length);
stream.WriteByte(0);
stream.WriteByte(0);
}

return StreamToBytes(stream);
}
2.ue4向C#发送string
这种情况,ue4端照常发送,c#解析的时候需要做一定处理

c#在接收到string数据时,先取出string长度信息,如果string长度>=0,则说明c#接收到的string是ascii编码,如果小于0,说明接收到的string是unicode编码

具体代码如下

public String GetString(byte[] data, int index, out int outIndex)
{
int strLen = System.BitConverter.ToInt32(data, index);
bool Ascii = strLen >= 0;
if (Ascii)
{
outIndex = index + 4 + strLen;

int begin = index + 4;
int end = outIndex;
byte[] byteStr = data.Skip(begin).Take(end - begin - 1).ToArray();

string str = Encoding.Default.GetString(byteStr);
return str;
}
else
{
strLen = -strLen;
outIndex = index + 4 + strLen*2;

int begin = index + 4;
int end = outIndex;
byte[] byteStr = data.Skip(begin).Take(end - begin - 2).ToArray();

string str = Encoding.Unicode.GetString(byteStr);
return str;
}
}
以上内容主要参考的是ue4中的源码,具体源码如下:
FArchive& operator<<( FArchive& Ar, FString& A )
{
// > 0 for ANSICHAR, < 0 for UCS2CHAR serialization

if (Ar.IsLoading())
{
int32 SaveNum;
Ar << SaveNum;

bool LoadUCS2Char = SaveNum < 0;
if (LoadUCS2Char)
{
SaveNum = -SaveNum;
}

// If SaveNum is still less than 0, they must have passed in MIN_INT. Archive is corrupted.
if (SaveNum < 0)
{
Ar.ArIsError = 1;
Ar.ArIsCriticalError = 1;
UE_LOG(LogNetSerialization, Error, TEXT("Archive is corrupted"));
return Ar;
}

auto MaxSerializeSize = Ar.GetMaxSerializeSize();
// Protect against network packets allocating too much memory
if ((MaxSerializeSize > 0) && (SaveNum > MaxSerializeSize))
{
Ar.ArIsError = 1;
Ar.ArIsCriticalError = 1;
UE_LOG( LogNetSerialization, Error, TEXT( "String is too large" ) );
return Ar;
}

// Resize the array only if it passes the above tests to prevent rogue packets from crashing
A.Data.Empty (SaveNum);
A.Data.AddUninitialized(SaveNum);

if (SaveNum)
{
if (LoadUCS2Char)
{
// read in the unicode string and byteswap it, etc
auto Passthru = StringMemoryPassthru<UCS2CHAR>(A.Data.GetData(), SaveNum, SaveNum);
Ar.Serialize(Passthru.Get(), SaveNum * sizeof(UCS2CHAR));
// Ensure the string has a null terminator
Passthru.Get()[SaveNum-1] = '\0';
Passthru.Apply();

INTEL_ORDER_TCHARARRAY(A.Data.GetData())

// Since Microsoft's vsnwprintf implementation raises an invalid parameter warning
// with a character of 0xffff, scan for it and terminate the string there.
// 0xffff isn't an actual Unicode character anyway.
int Index = 0;
if(A.FindChar(0xffff, Index))
{
A[Index] = '\0';
A.TrimToNullTerminator();
}
}
else
{
auto Passthru = StringMemoryPassthru<ANSICHAR>(A.Data.GetData(), SaveNum, SaveNum);
Ar.Serialize(Passthru.Get(), SaveNum * sizeof(ANSICHAR));
// Ensure the string has a null terminator
Passthru.Get()[SaveNum-1] = '\0';
Passthru.Apply();
}

// Throw away empty string.
if (SaveNum == 1)
{
A.Data.Empty();
}
}
}
else
{
bool SaveUCS2Char = Ar.IsForcingUnicode() || !FCString::IsPureAnsi(*A);
int32 Num = A.Data.Num();
int32 SaveNum = SaveUCS2Char ? -Num : Num;

Ar << SaveNum;

A.Data.CountBytes( Ar );

if (SaveNum)
{
if (SaveUCS2Char)
{
// TODO - This is creating a temporary in order to byte-swap. Need to think about how to make this not necessary.
#if !PLATFORM_LITTLE_ENDIAN
FString ATemp = A;
FString& A = ATemp;
INTEL_ORDER_TCHARARRAY(A.Data.GetData());
#endif

Ar.Serialize((void*)StringCast<UCS2CHAR>(A.Data.GetData(), Num).Get(), sizeof(UCS2CHAR)* Num);
}
else
{
Ar.Serialize((void*)StringCast<ANSICHAR>(A.Data.GetData(), Num).Get(), sizeof(ANSICHAR)* Num);
}
}
}

return Ar;
}
注意,ue4,发送和接收数据都是用这段代码,Ar.IsLoading()为true代表接收数据,否则为发送数据
---------------------
作者:--小智--
来源:CSDN
原文:https://blog.csdn.net/XIAOZHI0999/article/details/80785570
版权声明:本文为博主原创文章,转载请附上博文链接!

ue4同c#通信时的中文乱码问题的更多相关文章

  1. [MacOS] 终端使用ssh时,中文乱码问题处理

    终端显示中文问题处理: vim ~/.inputrc 加入以下代码 set meta-flag on set convert-meta off set input-meta on set output ...

  2. 解决在Linux下安装Oracle时的中文乱码问题

    本帖最后由 TsengYia 于 2012-2-22 17:06 编辑 解决在Linux下安装Oracle时的中文乱码问题 操作系统:Red Hat Enterprise Linux 6.1数据库:O ...

  3. (转)MySQL 插入数据时,中文乱码问题的解决

    MySQL 插入数据时,中文乱码问题的解决  原文:http://www.cnblogs.com/sunzn/archive/2013/03/14/2960248.html 当向 MySQL 数据库插 ...

  4. IDEA使用maven构建时控制台中文乱码的解决办法

    使用maven clean install 项目时控制台中文乱码,解决办法如下: Setting->maven->runner VMoptions: -Dfile.encoding=UTF ...

  5. source命令 导入.sql文件时,中文乱码 或者是注释乱码

    1.source命令 导入.sql文件时,中文乱码 或者是注释乱码 首先进入dos命令,进入mysql数据库,之后use 数据库:之后查看你的mysql数据库编码 如下命令:模糊查询变量charact ...

  6. Java通信过程的中文乱码的解决

    J在基于Java的编程中,常常会碰到汉字的处里及显示的问题.比方一大堆乱码或问号. 这是由于JAVA中默认的编码方式是UNICODE.而中国人通常使用的文件和DB都是基于GB2312或者BIG5等编码 ...

  7. 关于struts2中表单提交时,中文乱码问题的解决

    http://blog.csdn.net/hjw506848887/article/details/8966194 今天写项目时,突然遇到了struts2中表单提交的中文乱码问题,调了好久就是不知道答 ...

  8. Tomcat 处理请求时的中文乱码问题

    利用Tomcat8作为服务器,采用servlet接收前端请求后进行处理的过程中,前台请求中有中文时,中文信息变成了乱码. 经过调试和查阅,发现Tomcat在处理get请求和post请求是有区别的.参照 ...

  9. action接收到来自jsp页面的请求时出现中文乱码问题处理方法

    写JSP程序时,在Servlet中取请求参数时出现了乱码,当然,这种乱码问题再简单不过了.由于在JSP中使用了GBK作用页面的编码,那么提交的中文信息自然也会被按着GBK进行编码,为%xx格式的GBK ...

随机推荐

  1. java基础之完数判断

    完数: 完全数(Perfect number),又称完美数或完备数,是一些特殊的自然数.它所有的真因子(即除了自身以外的约数)的和(即因子函数),恰好等于它本身.如果一个数恰好等于它的因子之和,则称该 ...

  2. 在AlexNet中LRN 局部响应归一化的理

    在AlexNet中LRN 局部响应归一化的理 一.LRN技术介绍: Local Response Normalization(LRN)技术主要是深度学习训练时的一种提高准确度的技术方法.其中caffe ...

  3. leetcode 75 Sorted Colors

    两种解法 1)记录0和1的个数 然后按照记录的个数将0和1重新放入原数组,剩下的补2 2)双指针left,right left表示0~left-1都为0,即i之前都为0 right表示right+1~ ...

  4. Elasticsearch系列(二)--query、filter、aggregations

    本文基于ES6.4版本,我也是出于学习阶段,对学习内容做个记录,如果文中有错误,请指出. 实验数据: index:book type:novel mappings: { "mappings& ...

  5. 1008-Redo

    关于flag,都立下了 T1 考试的时候就觉得是贪心,但是不会反悔emm…… 于是正解就是一个堆优化可反悔的贪心=.= 每次找前面最小的,于是是小根堆. 我们在交易的时候发现后面的一个可以更优. 于是 ...

  6. 组件:事件传递$emit

    <!DOCTYPE html> <html lang="zh"> <head> <title></title> < ...

  7. <form>(表单)标签和常用的类型

    1.定义和用法 <form> 标签用于为用户输入创建 HTML 表单. 表单能够包含 input 元素,比如文本字段.复选框.单选框.提交按钮等等. 表单还可以包含 menus.texta ...

  8. JS 中 Tween 的使用

    JavaScript Tween算法及缓动效果   Flash做动画时会用到Tween类,利用它可以做很多动画效果,例如缓动.弹簧等等.我这里要教大家的是怎么利用flash的Tween类的算法,来做j ...

  9. DSP日志打印 LOG_printf

    LOG_printf 依托BIOS环境,需要引用下列头文件: #include <std.h> #include <log.h>     并且,要在.tcf环境中添加一个LOG ...

  10. Jmeter运行原理

    Jmeter运行原理: JMETER是运行在JVM虚拟机上的,每个进程的开销比loadrunner的进程开销大,如果以进程的方式来运行每台负载机上的进程数量不会允许太多,当有大量并发时就需要大量的负载 ...