精易论坛

标题: [洫蜘蛛] 编码转换模块! [打印本页]

作者: 洫蜘蛛    时间: 2018-10-20 10:39
标题: [洫蜘蛛] 编码转换模块!
本帖最后由 洫蜘蛛 于 2018-10-20 10:42 编辑

易语言的使用中,不可避免的需要转换文本的编码,众所周知,大家都用这两个API:
  1. MultiByteToWideChar
  2. WideCharToMultiByte
复制代码

但是,这两个API稍微不对就得叫你的程序完蛋!!!
昨晚又仔细参考的MSDN文档,有两个关键字非常需要注意:
  1. 字符
  2. 字节
复制代码

是的,字符和字节,一个参数指定的是缓冲区字符数,一个是缓冲区字节数。
所以,这次我直接根据编码的最大可能字节数来手动计算缓冲区大小。
例如:UTF8,一个字符最多使用6个字节,转换时缓冲区大小就设为字符数的6倍大小字节空间。
预览图:

安全的做法是直接申请足够大的空间来进行转换,所以重新封装了一下编码转换!
请尽量在XP系统并且多线程环境下测试,有问题欢迎联系反馈!

下面上模块源码:
编码转换.e (9.24 KB, 下载次数: 150)


作者: a16633    时间: 2018-10-20 10:51
转换速度快吗 像精易那个编码转换速度就超级慢
作者: 洫蜘蛛    时间: 2018-10-20 10:56
a16633 发表于 2018-10-20 10:51
转换速度快吗 像精易那个编码转换速度就超级慢

这个速度应该蛮快的了,虽然还能提速,但是暂时先这样。
这次发的主要是避免编码转换时造成的程序崩溃问题
这两个API很容易造成程序崩溃的。

作者: 福仔    时间: 2018-10-20 11:07
注意:使用MultiByteToWideChar函数可能会危及应用程序的安全性。调用此函数很容易导致缓冲区溢出,因为lpMultiByteStr指示的输入缓冲区的大小等于字符串中的字节数,而lpWideCharStr指示的输出缓冲区的大小等于字符数。为避免缓冲区溢出,应用程序必须指定适合缓冲区接收的数据类型的缓冲区大小。

cbMultiByte
由lpMultiByteStr指示的缓冲区的大小(以字节为单位)。如果此参数设置为0,则该函数返回lpMultiByteStr所需的缓冲区大小,并且不使用输出参数本身。

cchWideChar
由lpWideCharStr指示的缓冲区的大小(以字符为单位)。如果此值为0,则该函数返回所需的缓冲区大小(以字符为单位),包括任何终止空字符,并且不使用lpWideCharStr缓冲区。

以上由msdn翻译过来的....
两个API都有个参数,填0返回缓冲区所需要的大小,所以 缓冲区大小还是交给他计算.........
作者: 福仔    时间: 2018-10-20 11:18
福仔 发表于 2018-10-20 11:07
注意:使用MultiByteToWideChar函数可能会危及应用程序的安全性。调用此函数很容易导致缓冲区溢出,因为lpM ...

如上面提到的那样,如果首先在cchWideChar设置为0的情况下调用此函数以便获得所需的大小,则输出缓冲区很容易溢出。如果使用MB_COMPOSITE标志,则每个输入字符的输出长度可以是三个或更多字符。

原来备注后面还有这么一段,由API计算的缓冲区容易造成缓冲区溢出....
作者: 镇坛道德标杆    时间: 2018-10-20 11:59
其实很简单, 给一段未知的字节, 无论它有没有字符串截止符\0, 既然要牺牲空间, 那最安全的办法就是多申请一个字符的长度(字符, 不是字节, 简而言之, 宽字符+2, 窄字符+1), 拷贝一份源数据, 用 strlen 就可以很安全地获取到该字符串的确切长度.

还有长度是可以传入的, 只需要保证正确就可以了, 不浪费空间的前提下一样可以保证正确性:

  
utf8_Len = 取字节集长度 (utf8)
如果真 (utf8_Len = 0)
返回 (“”)

pUtf8 = 取变量数据地址_字节集 (utf8)
utf8_Len2 = lstrlenA (pUtf8)
如果真 (0 ≤ utf8_Len2 utf8_Len2 ≤ utf8_Len)
utf8_Len = utf8_Len2

这样就把几种错误的情况都考虑到了:
1.有且仅有一个截止符, 而且截止符在字符串的结尾;
2.截止符在字符串的中间;
3.没有截止符.

至于 utf-8 的 6 倍我觉得实在有点浪费, 这两个出错有两种原因: 一是因为没有截止符导致缓冲区过大, 二是没有分清楚宽窄字节的长度的区别导致缓冲区过小。

作者: 镇坛道德标杆    时间: 2018-10-20 12:00
本帖最后由 镇坛道德标杆 于 2018-10-20 12:02 编辑

# 论坛抽风   发重复了
作者: sampo    时间: 2018-10-20 14:24
感谢楼主分享源码及经验
作者: jr21066    时间: 2018-10-20 14:42
又百度了一下.原来是un码车utf8时会产生6字节.
作者: 洫蜘蛛    时间: 2018-10-20 17:39
福仔 发表于 2018-10-20 11:18
如上面提到的那样,如果首先在cchWideChar设置为0的情况下调用此函数以便获得所需的大小,则输出缓冲区很 ...

所以明白我为何要自行计算空间而不用api去计算了
作者: yunying    时间: 2018-10-22 19:42
提示: 作者被禁止或删除 内容自动屏蔽
作者: yunying    时间: 2018-10-22 19:42
提示: 作者被禁止或删除 内容自动屏蔽
作者: huhua    时间: 2018-10-25 05:44
谢谢分享。感谢
作者: 安与好    时间: 2018-10-25 06:24
支持开源~!感谢分享
作者: saina6282    时间: 2023-1-2 14:57
感谢分享,很给力
作者: saina6282    时间: 2023-1-2 14:57
66666666666666666666
作者: shareyi    时间: 2023-6-24 15:53
非常感谢
作者: shareyi    时间: 2023-6-24 15:55
非常感谢
作者: mnin    时间: 2024-6-1 11:17
非常感谢




欢迎光临 精易论坛 (https://125.confly.eu.org/) Powered by Discuz! X3.4