如何用C#序列化含Unicode与非Unicode字符串并实现C++反序列化
C# 序列化混合Unicode/非Unicode字符串适配C++反序列化方案
我之前刚好处理过类似的跨语言序列化场景,结合你提到的C++端核心逻辑(将非Unicode字符转成对应Unicode等价形式,统一序列化Unicode字符串),给你一套能完美适配的C#实现方案,保证两端兼容性:
核心对齐思路
首先要明确:C#中的string本身就是基于UTF-16的Unicode字符串,所以核心任务不是“转换”,而是确保输入字符串的所有字符都对应正确的Unicode码点,然后按照和C++端一致的二进制格式写入文件。
如果你的输入字符串来自非Unicode编码的数据源(比如GB2312、ISO-8859-1的字节流),第一步要做的是用对应的编码将字节解码成标准的UTF-16字符串;如果字符串已经是C#原生的string(不管混合了什么字符),那直接进入序列化步骤即可。
C# 序列化实现代码
下面是完整的序列化方法,包含预处理和写入逻辑,注释里标注了和C++端对齐的关键点:
using System.IO; using System.Text; public static class StringSerializer { public static void SerializeToBinary(string inputString, string outputFilePath) { // 1. 预处理:如果输入来自非Unicode数据源,先解码为UTF-16字符串 // 示例:如果原数据是ISO-8859-1编码的字节,先解码 // byte[] rawBytes = File.ReadAllBytes("non-unicode-source.txt"); // string inputString = Encoding.GetEncoding("ISO-8859-1").GetString(rawBytes); // 2. 将UTF-16字符串转换为字节数组(使用UTF-16LE,和Windows平台C++的wchar_t对齐) byte[] unicodeBytes = Encoding.Unicode.GetBytes(inputString); // 3. 写入文件:先写字符串长度(字符数,和C++端读取逻辑一致),再写字节流 using (FileStream fs = new FileStream(outputFilePath, FileMode.Create, FileAccess.Write)) using (BinaryWriter writer = new BinaryWriter(fs, Encoding.Unicode)) { // 写入字符数(注意:如果C++端是按字节数读取,这里要改成unicodeBytes.Length) writer.Write(inputString.Length); // 写入UTF-16LE字节 writer.Write(unicodeBytes); } } }
和C++反序列化的适配要点
- 编码对齐:C#中
Encoding.Unicode对应UTF-16LE,这和Windows平台下C的wchar_t(16位小端)完全匹配,确保C端读取后能直接解析为std::wstring。 - 长度标识:代码中写入的是字符串的字符数,如果你的C端是按字节数读取,把
writer.Write(inputString.Length)改成writer.Write(unicodeBytes.Length)即可,必须和C端的读取逻辑严格一致。 - 非Unicode字符处理:如果C++端是把ISO-8859-1这类单字节编码的字符转成对应Unicode码点(比如0xC9 → U+00C9),C#中只要用对应编码解码原字节,就能得到完全一致的Unicode字符,不需要额外转换。
测试验证建议
你可以用一个混合字符的字符串做测试,比如:
string testString = "中文测试 Ééññ"; // 包含Unicode中文和ISO-8859-1的特殊字符 StringSerializer.SerializeToBinary(testString, "test.bin");
然后用你的C++反序列化器读取test.bin,应该能得到完全一致的字符串。
内容的提问来源于stack exchange,提问作者zeb




