多字节与UTF-8、 Unicode之间的转换
VC中Ansi、 Unicode、 UTF8字符串之间的转换和写入文本
An si字符串我们最熟悉英文占一个字节汉字2个字节 以一个\0结尾常用于txt文本文件
Unicode字符串每个字符(汉字、英文字母)都占2个字节 以2个连续的\0结尾 NT操作系统内核用的是这种字符串常被定义为typedef unsigned short wchar_t;所以我们有时常会见到什么char*无法转换为unsigned short*之类的错误其实就是unicode
UTF8是Unicode一种压缩形式英文A在unicode中表示为0x0041 老外觉得这种存储方式太浪费因为浪费了50%的空间于是就把英文压缩成1个字节成了u tf8编码但是汉字在u tf8中占3个字节显然用做中文不如a ns i合算这就是中国的网页用作a n s i编码而老外的网页常用utf8的原因。
UTF8在还游戏里运用的很广泛 比如WOW的lua脚本等
下面来说一下转换主要用代码来说明吧
写文件我用了CFi le类其实用FILE*之类的也是一样写文件和字符串什么类别没有关系硬件只关心数据和长度
Ansi转Unicode
介绍2种方法void CConvertDlg: :OnBnCl ickedButtonAnsiToUnicode()
{
//ansi to unicodechar*szAnsi="abcd1234你我他";
//预转换得到所需空间的大小int wcsLe n =: :MultiByteToWideChar(CP_ACP, NULL, szAnsi , strlen(szAnsi), NULL,
0);
//分配空间要给'\0'留个空间 MultiByteToWideChar不会给'\0'空间wchar_t*wszString=newwchar_t[wcsLen+1];
//转换
: :MultiByteToWideChar(CP_ACP,NULL,szAnsi ,strlen(szAnsi),wszSt ring,wcsLen);
//最后加上'\0'wszString[wcsLen]='\0';
//unicode版的MessageBoxAPI
: :MessageBoxW(GetSafeHwnd(),wszString,wszString,MB_OK);
//接下来写入文本
//写文本文件头2个字节0xfeff低位0xff写在前
CFi lecFi le;cFi le.Open(_T("1 .txt"),CFi le: :modeWrite|CFi le: :modeCreate);
//文件开头cFi le.SeekToBegin();cFi le.Write("\xff\xfe",2);
//写入内容cFi le.Write(wszString,wcsLen*sizeof(wchar_t));cFi le.Flush();cFi le.Close();delete[]wszString;wszSt ring=NULL;
//方法2
//设置当前地域信息不设置的话使用这种方法 中文不会正确显示
//需要#include<locale.h>setlocale(LC_CTYPE, "chs");wchar_t wcsStr[100];
//注意下面是大写S在unicode中代表后面是ansi字符串
//swprintf是sprintf的unicode版本
//格式的前面要加大写L代表是unicodeswprintf(wcsStr, L"%S",szAns i);
: :MessageBoxW(GetSafeHwnd(),wcsStr,wcsStr,MB_OK);
}
Unicode转Ansi
也是2种方法void CConvertDlg: :OnBnCl ickedButtonUnicodeToAnsi()
{
//unicode to ansiwchar_t*wszString=L"abcd1234你我他";
//预转换得到所需空间的大小这次用的函数和上面名字相反int ansiLen =: :WideCharToMultiByte(CP_ACP, NULL,wszString,wcslen(wszString),NULL,0,NULL,NULL);
//同上分配空间要给'\0'留个空间char*szAnsi=newchar[ansiLen+1];
//转换
//unicode版对应的strlen是wcslen
: :WideCharToMultiByte(CP_ACP, NULL, wszString, wcslen(wszSt ring), szAnsi ,ansiLen,NULL,NULL);
//最后加上'\0'szAnsi[ansiLen]='\0' ;
//Ansi版的MessageBoxAPI
: :MessageBoxA(GetSafeHwnd(),szAnsi ,szAnsi ,MB_OK);
//接下来写入文本
//写文本文件 ANSI文件没有BOM
CFi lecFi le;cFi le.Open(_T("1.txt"),CFi le: :modeWrite|CFi le: :modeCreate);
//文件开头cFi le.SeekToBegin();
//写入内容cFi le.Write(szAnsi ,ansiLen*sizeof(char));cFi le.Flush();cFi le.Close();delete[]szAnsi ;szAnsi=NULL;
//方法2
//和上面一样有另一种方法setlocale(LC_CTYPE, "chs");char szStr[100];
//注意下面是大写在ansi中代表后面是unicode字符串
//sprintfsprintf(szStr, "%S",wszSt ring);
: :MessageBoxA(GetSafeHwnd(),szStr,szStr,MB_OK);
}
Unicode转UTF8void CConvertDlg: :OnBnCl ickedButtonUnicodeToU8()
{
//unicode to UTF8wchar_t*wszString=L"abcd1234你我他";
//预转换得到所需空间的大小这次用的函数和上面名字相反int u 8Len =: :WideCharToMultiByte(CP_UTF8, NULL,wszSt ring,wcslen(wszString),NULL,0,NULL,NULL);
//同上分配空间要给'\0'留个空间
//UTF8虽然是Unicode的压缩形式但也是多字节字符串所以可以以char的形式保存char*szU8=new char[u8Len+1];
//转换
//unicode版对应的strlen是wcslen
: :WideCharToMultiByte(CP_UTF8,NULL,wszSt ring,wcslen(wszString), szU8, u8Len,NULL,NULL);
//最后加上'\0'szU8[u8Len]='\0' ;
//MessageBox不支持UTF8,所以只能写文件
//接下来写入文本
//写文本文件 UTF8的BOM是0xbfbbef
CFi lecFi le;cFi le.Open(_T("1 .txt"),CFi le: :modeWrite|CFi le: :modeCreate);
//文件开头cFi le.SeekToBegin();
//写BOM 同样低位写在前cFi le.Write("\xef\xbb\xbf",3);
//写入内容cFi le.Write(szU8, u8Len*sizeof(char));cFi le.Flush();cFi le.Close();delete[]szU8;szU8=NULL;
}
UTF8转UNICO DEvoid CConvertDlg: :OnBnCl ickedButtonU8ToUnicode()
{
//UTF8 to Unicode
//由于中文直接复制过来会成乱码编译器有时会报错故采用16进制形式char*szU8="abcd 1234\xe4\xbd\xa0\xe6\x88\x91\xe4\xbb\x96\x00";
//预转换得到所需空间的大小int wcsLen=: :MultiByteToWideChar(CP_UTF8,NULL,szU8,strlen(szU8),NULL,0);//分配空间要给'\0'留个空间 MultiByteToWideChar不会给'\0'空间wchar_t*wszString=newwchar_t[wcsLen+1];
//转换
: :MultiByteToWideChar(CP_UTF8,NULL,szU8,strlen(szU8),wszString,wcsLen);//最后加上'\0'wszString[wcsLen]='\0';
//unicode版的MessageBoxAPI
: :MessageBoxW(GetSafeHwnd(),wszString,wszString,MB_OK);
//写文本同ansi to unicode
}
An si转换utf8和utf8转换An si就是上面2个的结合把u n icod e作为中间量进行2次转换即可
#include<iostream>
#include<string>
#include<Windows.h>using namespace std;
void unicodeToUTF8(constwstring&src,string&result)
int n=WideCharToMultiByte(CP_UTF8,0,src.c_str(), -1 ,0,0,0,0);result.resize(n);
: :WideCharToMultiByte(CP_UTF8,0,src.c_str(), -1 , (char*)result.c_str(), result. length(),0,0);
void unicodeToGB2312(constwstring&wstr ,string&result)
int n=WideCharToMultiByte(CP_ACP, 0,wstr.c_str(), -1 ,0,0,0,0);result.resize(n);
: :WideCharToMultiByte(CP_ACP, 0,wstr.c_str(), -1 , (char*)result.c_str(), n,0,0);
void utf8ToUnicode(const string&src,wstring&result)
int n=MultiByteToWideChar(CP_UTF8,0,src.c_str(), -1 ,NULL,0);result.resize(n);
: :MultiByteToWideChar(CP_UTF8,0,src.c_str(), -1 , (LPWSTR)result.c_str(), result. len g th());
void gb2312ToUnicode(const string&src,wstring&result)
int n=MultiByteToWideChar(CP_ACP, 0,src.c_str(), -1 ,NULL,0);result.resize(n);
: :MultiByteToWideChar(CP_ACP, 0,src.c_str(), -1 , (LPWSTR)result.c_str(), result. length());
昨天晚上有收到VULTR服务商的邮件,如果我们有清楚的朋友应该知道VULTR对于新注册用户已经这两年的促销活动是有赠送100美元最高余额,不过这个余额有效期是30天,如果我们到期未使用完的话也会失效的。但是对于我们一般用户来说,这个活动还是不错的,只需要注册新账户充值10美金激活账户就可以。而且我们自己充值的余额还是可以继续使用且无有效期的。如果我们有需要申请的话可以参考"2021年最新可用Vul...
近期联通CUVIP的线路(AS4837线路)非常火热,妮妮云也推出了这类线路的套餐以及优惠,目前到国内优质线路排行大致如下:电信CN2 GIA>联通AS9929>联通AS4837>电信CN2 GT>普通线路,AS4837线路比起前两的优势就是带宽比较大,相对便宜一些,所以大家才能看到这个线路的带宽都非常高。妮妮云互联目前云服务器开放抽奖活动,每天开通前10台享3折优惠,另外...
昨天有分享到"2021年Vultr新用户福利注册账户赠送50美元"文章,居然还有网友曾经没有注册过他家的账户,薅过他们家的羊毛。通过一阵折腾居然能注册到账户,但是对于如何开通云服务器稍微有点不对劲,对于新人来说确实有点疑惑。因为Vultr采用的是预付费充值方式,会在每月的一号扣费,当然我们账户需要存留余额或者我们采用自动扣费支付模式。把笔记中以前的文章推送给网友查看,他居然告诉我界面不同,看的不对...