BIG5编码转为gb2312编码
big5和gb2312都是双字节编码,一个用于早期的繁体字编码,一个是简体字的编码所以想问问是否有什么算法可以直接把繁体的big5的文字编码转换成gb2312编码的方法
在线工具 本帖最后由 爱飞的猫 于 2024-5-25 09:22 编辑
不是所有的简体中文字符都可以映射到 BIG5(虽然包括了很大一部分),也不是所有的繁体中文字符都可以映射到 GBK 等编码。
不过微软提供了简繁转换接口,`LCMapStringEx`,可以将 Unicode 字符串中的简体和繁体仅限转换(不包括当地特有词汇)。
因此,你可以:
- BIG5 繁体字符转到 Unicode
- 使用 `LCMapStringEx` 将 Unicode 字符串的繁体字符映射到简体字符
- 最后将这段 Unicode 字符串转换到 GBK。
测试代码:
```cpp
#include <string>
#include <iostream>
#include <windows.h>
#include <ctype.h>
#include <stdio.h>
// 以十六进制视图打印
void hexdump(const void* ptr, int buflen) {
auto* buf = (const unsigned char*)ptr;
int i, j;
for (i = 0; i < buflen; i += 16) {
printf("%06x: ", i);
for (j = 0; j < 16; j++)
if (i + j < buflen)
printf("%02x ", buf);
else
printf(" ");
printf(" ");
for (j = 0; j < 16; j++)
if (i + j < buflen)
printf("%c", isprint(buf) ? buf : '.');
printf("\n");
}
}
template <typename CONTAINER>
void hexdump(CONTAINER& str)
{
hexdump(reinterpret_cast<const void*>(str.data()), str.size() * sizeof(str));
}
// 代码页信息
// https://learn.microsoft.com/wind ... de-page-identifiers
constexpr int kCodePageGB2312 = 936; // 简体 (GB2312)
constexpr int kCodePageGB18030 = 54936; // 简体 (GB18030)
constexpr int kCodePageBig5 = 950; // 繁体
// 简单的 Ansi/Unicode 互转
std::wstring A2W(const std::string& ansi, int codePage = CP_ACP)
{
int len = MultiByteToWideChar(codePage, 0, ansi.c_str(), -1, NULL, 0);
std::wstring wide(len, 0);
MultiByteToWideChar(codePage, 0, ansi.c_str(), -1, &wide, len);
return wide;
}
std::string W2A(const std::wstring& wide, int codePage = CP_ACP)
{
int len = WideCharToMultiByte(codePage, 0, wide.c_str(), -1, NULL, 0, nullptr, NULL);
std::string ansi(len, 0);
WideCharToMultiByte(codePage, 0, wide.c_str(), -1, &ansi, len, nullptr, NULL);
return ansi;
}
int main()
{
std::wstring text_src = L"吾爱破解论坛 - 爱飞的猫";
// 简转繁
std::wstring text_trad(text_src.size(), 0);
LCMapStringEx(LOCALE_NAME_INVARIANT, LCMAP_TRADITIONAL_CHINESE, text_src.c_str(), text_src.size(), &text_trad, text_trad.size(), nullptr, nullptr, 0);
std::wcout << L"繁体后: " << text_trad << L'\n';
std::cout << "trad(bytes)\n";
hexdump(text_trad);
// 繁转简
std::wstring text_simp(text_trad.size(), 0);
LCMapStringEx(LOCALE_NAME_INVARIANT, LCMAP_SIMPLIFIED_CHINESE, text_trad.c_str(), text_trad.size(), &text_simp, text_simp.size(), nullptr, nullptr, 0);
std::wcout << L"简体后: " << text_trad << L'\n';
std::cout << "simp(bytes)\n";
hexdump(text_simp);
// 繁(Unicode) 转 BIG5
auto text_trad_big5 = W2A(text_trad, kCodePageBig5);
std::cout << "text_trad_big5(bytes)\n";
hexdump(text_trad_big5);
// 简(Unicode) 转 BIG5
auto text_simp_big5 = W2A(text_simp, kCodePageBig5);
std::cout << "text_simp_big5(bytes)\n";
hexdump(text_simp_big5);
// 繁(Unicode) 转 GB18030
auto text_trad_GB18030 = W2A(text_trad, kCodePageGB18030);
std::cout << "text_trad_GB18030(bytes)\n";
hexdump(text_trad_GB18030);
// 简(Unicode) 转 GB18030
auto text_simp_GB18030 = W2A(text_simp, kCodePageGB18030);
std::cout << "text_simp_GB18030(bytes)\n";
hexdump(text_simp_GB18030);
return 0;
}
```
转换结果:
```
trad(bytes)
000000: 3e 54 1b 61 34 78 e3 89 d6 8a c7 58 20 00 2d 00>T.a4x.....X .-.
000010: 20 00 1b 61 db 98 84 76 93 8c ..a...v..
simp(bytes)
000000: 3e 54 31 72 34 78 e3 89 ba 8b 5b 57 20 00 2d 00>T1r4x....[W .-.
000010: 20 00 31 72 de 98 84 76 2b 73 .1r...v+s
text_trad_big5(bytes)
000000: a7 5e b7 52 af 7d b8 d1 bd d7 be c2 20 2d 20 b7.^.R.}...... - .
000010: 52 ad b8 aa ba bf df 00 R.......
text_simp_big5(bytes)
000000: a7 5e 3f af 7d b8 d1 3f 3f 20 2d 20 3f 3f aa ba.^?.}..?? - ??..
000010: 3f 00 ?.
text_trad_GB18030(bytes)
000000: ce e1 90 db c6 c6 bd e2 d5 93 89 af 20 2d 20 90............ - .
000010: db ef 77 b5 c4 d8 88 00 ..w.....
text_simp_GB18030(bytes)
000000: ce e1 b0 ae c6 c6 bd e2 c2 db cc b3 20 2d 20 b0............ - .
000010: ae b7 c9 b5 c4 c3 a8 00 ........
```
放到十六进制编辑器看看(调整好代码页):
![](https://imgsrc.baidu.com/forum/pic/item/a8ec8a13632762d0f0154e82e6ec08fa513dc6e0.png)
可以看到如果不进行字符映射,转换到 BIG5 编码后会缺字(显示为问号)。
本帖最后由 xuanle6 于 2024-5-25 10:35 编辑
//Delphi语言
// GBK-->GB2312
// 中華人民共和國 --> 中华人民共和国
function GBCht2Chs(const GBStr: string): AnsiString;
var
SourceLength: integer;
begin
SourceLength := Length(GBStr) + 1;
SetLength(result, SourceLength);
//GB CHS -> GB CHT
LCMapString($804, LCMAP_SIMPLIFIED_CHINESE, @GBStr, SourceLength, @result, SourceLength);
end;
// GB2312-->GBK
// 中华人民共和国 --> 中華人民共和國
function GBChs2Cht(const GBStr: string): AnsiString;
var
SourceLength: integer;
begin
SourceLength := Length(GBStr) + 1;
SetLength(result, SourceLength);
LCMapString($804, LCMAP_TRADITIONAL_CHINESE, @GBStr, SourceLength, @result, SourceLength);
end;
Word 有转存功能 非常感谢楼上几位朋友的热心回复,我是想不借助编译器自带的函数来进行转换,就是想问问看有什么算法来自己转换,看起来要么用编译器的函数转换,要么只能自己写一个映射表来进行硬转换了:'(weeqw kof888 发表于 2024-5-25 11:50
非常感谢楼上几位朋友的热心回复,我是想不借助编译器自带的函数来进行转换,就是想问问看有什么算法来自己 ...
https://www.qqxiuzi.cn/zh/hanzi-unicode-bianma.php
unicode编码表 flyer_2001 发表于 2024-5-25 13:40
https://www.qqxiuzi.cn/zh/hanzi-unicode-bianma.php
unicode编码表
感谢回复 ,Unicode编码算是可变长度的编码,编码长度不是固定的。
不过这贴我只是想了解一下繁体转简体的算法,看起来没有,只能自己做一个映射表来解决 kof888 发表于 2024-5-25 17:41
感谢回复 ,Unicode编码算是可变长度的编码,编码长度不是固定的。
不过这贴我只是想了解一下繁体转简 ...
微软的 Unicode(UTF-16-le)是固定长度,每个字符使用双字节表示。 kof888 发表于 2024-5-25 11:50
非常感谢楼上几位朋友的热心回复,我是想不借助编译器自带的函数来进行转换,就是想问问看有什么算法来自己 ...
这不是编译器的函数,是微软系统 dll 提供的。
例如 (https://learn.microsoft.com/wind ... innls-lcmapstringex),你可以看到底部写的该函数来自 `Kernel32.dll`,支持 Windows Vista 及以上系统。
如果不想用它,只能和你说的一样在程序内硬编码对应的字符映射表了。
页:
[1]
2