Golang Go语言中如何将字节流里的C++ TCHAR转成string?

发布于 1周前 作者 h691938207 来自 Go语言

Golang Go语言中如何将字节流里的C++ TCHAR转成string?
和别人对接项目,用 websocket 传输数据,对方是 c++的,直接用结构体这种序列化方式。
tchar 怎么转换 go 的 string 呢? go 的 string 又怎么转换成 tchar 呢?
c++那边使用 unicode,tchar 大小为 2
我不会 c++,底层比较薄弱。请教下各位大佬
解决的可以发个红包答谢

9 回复

go 的 string 是 utf-8,windows 上的 cplusplus 的 tchar 定义了_UNICODE 宏之后是 uft-16,没定义是操作系统本地的编码(中文简体系统是 gbk )

更多关于Golang Go语言中如何将字节流里的C++ TCHAR转成string?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


最简单的方法是约定一种编码,传输汉字编码的十六进制字符串,而不是十六进制值,也就是纯 ascii 码,发送方编码,接收方解码,类似网页图片用 base64

go 标准库 unicode/utf16 有个 Encode 函数,把 uft-32 转成 utf-16, go 中的字符串能直接显式转成[]rune 类型

给个小建议,网络传字符尽量用 utf-8,后面能少好多问题。
TCHAR 本身是 Win32 下的宏定义,字节数和编码不确定,不建议直接用在网络或者文件相关的模块上。

TCHAR 是个宏,用来控制使用 char 还是 wchar_t 作为字符类型。


然而……
用哪种 char 作为字符类型并不能代表字符串用哪种编码格式储存
用哪种 char 作为字符类型并不能代表字符串用哪种编码格式储存
用哪种 char 作为字符类型并不能代表字符串用哪种编码格式储存



也就是说,完全可以用单字节 char string 来存变长编码 unicode ( utf8 ),也可以用单字节 char string 存(伪)定长编码 utf16 ;也可以用 wchar_t 去存 utf16 这样一般一个 wchar_t 刚好能放一个 utf16 的编码序列……微软曾是这么想的但现在证明想法很蠢。

对于完全不需要跟 windows API 打交道的数据,应当一律使用单字节字符 char 类型并采用 utf8 编码来存储字符串。当要使用 windows API 时转成 utf16。

如果对方的代码不用到 windowsAPI (尤其指 xxxA 和 xxxW 有区别的 API 如 MessageBoxW ),那么只用 ANSI 字符编译的版本也就是 TCHAR 定义为 char 的版本也不会有问题。

当然一般不是这种情况

另一种情况 TCHAR 被定义成 wchar_t,使用 utf16 编码,但在内存层面来看并不需要知道一个字符被定义成了多大,byte 序列都是一样的,把整段内存以 utf16 的方式 decode 即可

叫他改成 json,不折腾

要看对方平台用什么方式编码,GBK,UTF8 都会导致不同的解码方式。建议在异构平台下都按照 protobuf 进行编码。

上 protobuf\json\xml

在Go语言中处理从C++传递过来的字节流,尤其是包含TCHAR类型的数据时,需要考虑TCHAR在不同平台(Windows和Linux)上的定义差异。在Windows上,TCHAR通常被定义为char(ANSI)或wchar_t(Unicode),具体取决于项目的字符集设置。

  1. 如果TCHAR是char(即ANSI字符)

    • 你可以直接将字节流作为[]byte处理,并使用string(byteSlice)将其转换为Go的string类型。
  2. 如果TCHAR是wchar_t(即宽字符)

    • 在C++端,通常需要将宽字符数据编码为UTF-8或UTF-16,然后再传递给Go。
    • 在Go端,接收到的字节流需要按对应的编码解码。如果是UTF-16,可以使用encoding/binary包处理,再转换为UTF-8编码的string
    • 例如,如果接收的是UTF-16LE编码的字节流,可以遍历字节流,每次读取两个字节(一个UTF-16字符),然后使用rune类型转换,最后拼接成string

示例代码(假设接收的是UTF-16LE编码的字节流):

import (
    "encoding/binary"
    "unicode/utf16"
    "unicode/utf8"
)

func tcharToString(data []byte) (string, error) {
    decoder := utf16.NewDecoder(binary.LittleEndian.NewReader(data))
    runes := make([]rune, 0, len(data)/2)
    for {
        r, _, err := decoder.ReadRune()
        if err != nil {
            break
        }
        runes = append(runes, r)
    }
    return string(utf8.EncodeRuneSlice([]byte{}, runes...)), nil
}

请根据具体场景调整编码和解码逻辑。

回到顶部