找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 5018|回复: 21

【VB6】把BSTR和ANSI/UNICODE/UNICODE-BE/UTF8字符串互相转换

[复制链接]
发表于 2021-9-3 15:28:19 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
首先说明:ANSIUNICODE、UNICODE-BE(UNICODE BIG ENDIAN)的名称可能有歧义,以上名称来自WINDOWS记事本“另存为”对话框的【编码选择】处。

BSTR就是VB的STRING字符串,它本质上是UNICODE字符串。但讽刺的是,VB的自带控件竟然都不支持UNICODE。比如你想在中文系统上用VB自带控件(比如LABEL和TEXTBOX)正确显示德语的变音字母,是不可能的。要做的这点,必须用API自行创建控件。

ANSI字符串是最常见的,等同于C语言里的CHAR[],它的格式可以简单理解为“英文字符1字节+非英文字符2字节”。它的缺点在于非英文字符的编码有N种方法,比如简体中文WINDOWS系统的汉字编码是GBK(兼容GB2312),繁体中文WINDOWS系统的汉字编码是BIG5。如果在繁体中文WINDOWS系统上保存一个ANSI格式文本文件放到简体中文WINDOWS系统上打开就会显示为乱码,反之亦然。如果你的程序用了A版本的API,比如【MessageBoxA(0,"字符串",0,0)】,那么在非简体中文WINDOWS系统上看到的弹框将会是乱码;如果你的程序用的是W版本的API,比如【MessageBoxW(0,L"字符串",0,0)】,那么在非简体中文WINDOWS系统上看到的弹框则是正常的。

UNICODE字符串等同于C语言里的WCHAR[],所有字符就一律2个字节。该编码全球通用,不受地区和系统的影响。但如果字符串主要由英文字符组成时,会造成大量空间浪费。比如ABCD的ANSI编码是\x41\x42\x43\x44,但UNICODE编码则是\x41\x0\x42\x0\x43\x0\x44\x0。

UNICODE-BE字符串就是把UNICODE字符串的2个字节的位置调换了一下。比如某个字符的UNICODE编码是0xAA55,那么UNICODE-BE的编码就是0x55AA。该编码全球通用,不受地区和系统的影响。

综合ANSI和UNICODE的优缺点,于是就有了UTF8。对于纯英文字符,UTF8和ANSI是兼容的;对于非英文字符,UTF8有一套固定编码方法。该编码全球通用,不受地区和系统的影响。UTF8的缺点是一个中文字符的长度可能高达3字节甚至4字节。

使用MultiByteToWideChar和WideCharToMultiByte能让VB字符串(BSTR)和其它字符串相互转换。

以下是测试(把代码复制并保存为FRM文件即可运行):
游客,如果您要查看本帖隐藏内容请回复

本帖被以下淘专辑推荐:

回复

使用道具 举报

发表于 2021-9-4 19:46:34 | 显示全部楼层
其实你所说的“UNICODE”是Win32编程里的“UNICODE宏”的概念,需要和Unicode编码形式的概念区分开。

Unicode使用32位整数存储每个字符,比如ABCD其实是41 00 00 00 42 00 00 00 43 00 00 00 44 00 00 00,看起来非常占空间,但它能表达的字符种类非常多,其中还包含了相当多的数量的Emoji表情字符等。

Win32编程的“UNICODE”其实使用的是UTF-16编码。其和UTF-8一样,是Unicode的压缩形式。通过判断高位的Bit组合来决定后续字节是否与当前字节共同组合为一个字符。

UTF-8、UTF-16都是Unicode的压缩形式,其压缩解压的算法十分简单,参考这个帖子可以不借助API进行其中的互转:10972

也可以参考这个更加早期的帖子:1676

顺带一提,VB6自带“StrConv”函数,可以进行字符串编码转换,和MultiByteToWideChar、WideCharToMultiByte的功能相同。
回复 赞! 靠!

使用道具 举报

 楼主| 发表于 2021-9-6 22:10:47 | 显示全部楼层
0xAA55 发表于 2021-9-4 19:46
其实你所说的“UNICODE”是Win32编程里的“UNICODE宏”的概念,需要和Unicode编码形式的概念区分开。

Unic ...

StrConv不好使,只能和UNICODE互相转换。

但是BSTR和UNICODE互相转换可以直接使用“等号”实现。
回复 赞! 靠!

使用道具 举报

发表于 2021-9-11 08:50:53 | 显示全部楼层
谢谢分享,学习了
回复 赞! 靠!

使用道具 举报

发表于 2021-11-12 21:19:07 | 显示全部楼层
dfdfdfdfdfdf
回复 赞! 靠!

使用道具 举报

发表于 2022-4-5 11:23:57 | 显示全部楼层
谢谢分享,学习了
回复 赞! 靠!

使用道具 举报

发表于 2022-5-13 15:37:14 | 显示全部楼层
此贴必火,占位刘留名~~~~
回复 赞! 靠!

使用道具 举报

发表于 2022-5-20 12:42:46 | 显示全部楼层
其实VB6点TextBox是可以做到显示Unicode字符的,首先需要给exe加入comctl32.dll 6.0清单,让控件获得视觉主题,然后文本不要通过.Text属性赋值,而是用GetClassInfoW去获取原生的W版Edit控件的WndProc,最后用CallWindowProcW来调用它并传人WM_SETTEXT消息。同理我们也可以利用DefWindowProcW函数来实现让VB6的Form窗口标题栏现实Unicode文本。

点评

谢谢,这个方法确实可行。  发表于 2022-5-24 14:24
回复 赞! 靠!

使用道具 举报

 楼主| 发表于 2022-5-20 14:53:14 | 显示全部楼层
系统消息 发表于 2022-5-20 12:42
其实VB6点TextBox是可以做到显示Unicode字符的,首先需要给exe加入comctl32.dll 6.0清单,让控件获得视觉主 ...

口说无凭,你也弄个DEMO并放出源码来。

https://www.0xaa55.com/thread-26616-1-1.html

点评

你自己试试吧,这个例子我已经给很多人写过多次了。  发表于 2022-5-21 23:44
回复 赞! 靠!

使用道具 举报

发表于 2022-5-20 17:20:26 | 显示全部楼层
认真学习
回复

使用道具 举报

发表于 2022-5-24 13:51:43 | 显示全部楼层
杠起来了?
回复

使用道具 举报

发表于 2023-5-6 17:23:24 | 显示全部楼层
6
回复

使用道具 举报

发表于 2023-5-11 22:53:05 | 显示全部楼层
谢谢高手
回复

使用道具 举报

发表于 2023-7-5 11:44:26 | 显示全部楼层
学习一下
回复

使用道具 举报

发表于 2023-7-6 10:22:11 | 显示全部楼层
来晚了啊
回复

使用道具 举报

发表于 2023-8-19 15:12:39 | 显示全部楼层
vb6 編碼就新手而言是個困擾,感謝分享學習。
回复 赞! 靠!

使用道具 举报

发表于 2023-9-26 18:00:27 | 显示全部楼层
谢谢分享!
回复

使用道具 举报

发表于 2024-6-1 11:48:46 | 显示全部楼层
大佬,请问如何识别这些字符是什么字符呢?
回复 赞! 靠!

使用道具 举报

发表于 2024-6-25 11:45:07 | 显示全部楼层
最近在处理旧程式中ANSI与Unicode处理,不知转换后与写入文档与读取文档是不是也是要历经相同步骤?
回复 赞! 靠!

使用道具 举报

本版积分规则

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-11-23 16:19 , Processed in 0.037374 second(s), 25 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表