Ansi、Unicode、UTF8字符串之间的转换,wprintf

一文带你弄懂C++中的ANSI、Unicode和UTF8三种字符编码及相互转换 本文详细介绍ANSI、Unicode和UTF8三种字符编码以及它们之间的相互转换,并给出了实际问题实例。 阅读详情
Ansi字符串我们最熟悉,英文占一个字节,汉字2个字节,以一个/0结尾,常用于txt文本文件
Unicode字符串,每个字符(汉字、 英文字母)都占2个字节,以2个连续的/0结尾,NT操作系统内核用的是这种字符串,常被定义为typedef unsigned short wchar_t;所以我们有时常会见到什么char*无法转换为unsigned short*之类的错误,其实就是unicode
UTF8是 Unicode一种压缩形式,英文A在unicode中表示为0x0041,老外觉得这种存储方式太浪费,因为浪费了50%的空间,于是就把英文压缩成1 个字节,成了utf8编码,但是汉字在utf8中占3个字节,显然用做中文不如ansi合算,这就是中国的网页用作ansi编码而老外的网页常用utf8 的原因。
UTF8在还游戏里运用的很广泛,比如WOW的lua脚本等

下面来说一下转换,主要用代码来说明吧
写文件我用了CFile类,其实用FILE*之类的也是一样,写文件和字符串什么类别没有关系,硬件只关心数据和长度

Ansi转Unicode
介绍2种方法

void CConvertDlg::OnBnClickedButtonAnsiToUnicode()
{
    
// ansi to unicode
    char* szAnsi = "abcd1234你我他";
    
//预转换,得到所需空间的大小
    int wcsLen = ::MultiByteToWideChar(CP_ACP, NULL, szAnsi, strlen(szAnsi), NULL, 0);
    
//分配空间要给'/0'留个空间,MultiByteToWideChar不会给'/0'空间
    wchar_t* wszString = new wchar_t[wcsLen + 1];
    
//转换
    ::MultiByteToWideChar(CP_ACP, NULL, szAnsi, strlen(szAnsi), wszString, wcsLen);
    
//最后加上'/0'
    wszString[wcsLen] = '/0';
    
//unicode版的MessageBox API
    ::MessageBoxW(GetSafeHwnd(), wszString, wszString, MB_OK);

    
//接下来写入文本
    
//写文本文件,头2个字节0xfeff,低位0xff写在前
    CFile cFile;
    cFile.Open(_T(
"1.txt"), CFile::modeWrite | CFile::modeCreate);
    
//文件开头
    cFile.SeekToBegin();
    cFile.Write(
"/xff/xfe", 2);
    
//写入内容
    cFile.Write(wszString, wcsLen * sizeof(wchar_t));
    cFile.Flush();
    cFile.Close();
    delete[] wszString;
    wszString 
=NULL;


    
//方法2
    
//设置当前地域信息,不设置的话,使用这种方法,中文不会正确显示
    
//需要#include<locale.h>
    setlocale(LC_CTYPE, "chs"); 
    wchar_t wcsStr[
100];
    
//注意下面是大写S,在unicode中,代表后面是ansi字符串
    
//swprintf是sprintf的unicode版本
    
//格式的前面要加大写L,代表是unicode
    swprintf(wcsStr, L"%S", szAnsi);
    ::MessageBoxW(GetSafeHwnd(), wcsStr, wcsStr, MB_OK);

}


Unicode转Ansi
也是2种方法

void CConvertDlg::OnBnClickedButtonUnicodeToAnsi()
{
    
// unicode to ansi
    wchar_t* wszString = L"abcd1234你我他";
    
//预转换,得到所需空间的大小,这次用的函数和上面名字相反
    int ansiLen = ::WideCharToMultiByte(CP_ACP, NULL, wszString, wcslen(wszString), NULL, 0, NULL, NULL);
    
//同上,分配空间要给'/0'留个空间
    char* szAnsi = new char[ansiLen + 1];
    
//转换
    
//unicode版对应的strlen是wcslen
    ::WideCharToMultiByte(CP_ACP, NULL, wszString, wcslen(wszString), szAnsi, ansiLen, NULL, NULL);
    
//最后加上'/0'
    szAnsi[ansiLen] = '/0';
    
//Ansi版的MessageBox API
    ::MessageBoxA(GetSafeHwnd(), szAnsi, szAnsi, MB_OK);

    
//接下来写入文本
    
//写文本文件,ANSI文件没有BOM
    CFile cFile;
    cFile.Open(_T(
"1.txt"), CFile::modeWrite | CFile::modeCreate);
    
//文件开头
    cFile.SeekToBegin();
    
//写入内容
    cFile.Write(szAnsi, ansiLen * sizeof(char));
    cFile.Flush();
    cFile.Close();
    delete[] szAnsi;
    szAnsi 
=NULL;


    
//方法2
    
//和上面一样有另一种方法
    setlocale(LC_CTYPE, "chs"); 
    
char szStr[100];
    
//注意下面是大写,在ansi中,代表后面是unicode字符串
    
//sprintf
    sprintf(szStr, "%S", wszString);
    ::MessageBoxA(GetSafeHwnd(), szStr, szStr, MB_OK);
}


Unicode转UTF8

void CConvertDlg::OnBnClickedButtonUnicodeToU8()
{
    
// unicode to UTF8
    wchar_t* wszString = L"abcd1234你我他";
    
//预转换,得到所需空间的大小,这次用的函数和上面名字相反
    int u8Len = ::WideCharToMultiByte(CP_UTF8, NULL, wszString, wcslen(wszString), NULL, 0, NULL, NULL);
    
//同上,分配空间要给'/0'留个空间
    
//UTF8虽然是Unicode的压缩形式,但也是多字节字符串,所以可以以char的形式保存
    char* szU8 = new char[u8Len + 1];
    
//转换
    
//unicode版对应的strlen是wcslen
    ::WideCharToMultiByte(CP_UTF8, NULL, wszString, wcslen(wszString), szU8, u8Len, NULL, NULL);
    
//最后加上'/0'
    szU8[u8Len] = '/0';
    
//MessageBox不支持UTF8,所以只能写文件

    
//接下来写入文本
    
//写文本文件,UTF8的BOM是0xbfbbef
    CFile cFile;
    cFile.Open(_T(
"1.txt"), CFile::modeWrite | CFile::modeCreate);
    
//文件开头
    cFile.SeekToBegin();
    
//写BOM,同样低位写在前
    cFile.Write("/xef/xbb/xbf", 3);
    
//写入内容
    cFile.Write(szU8, u8Len * sizeof(char));
    cFile.Flush();
    cFile.Close();
    delete[] szU8;
    szU8 
=NULL;

}

UTF8转UNICODE

void CConvertDlg::OnBnClickedButtonU8ToUnicode()
{
    
//UTF8 to Unicode
    
//由于中文直接复制过来会成乱码,编译器有时会报错,故采用16进制形式
    char* szU8 = "abcd1234/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 = new wchar_t[wcsLen + 1];
    
//转换
    ::MultiByteToWideChar(CP_UTF8, NULL, szU8, strlen(szU8), wszString, wcsLen);
    
//最后加上'/0'
    wszString[wcsLen] = '/0';
    
//unicode版的MessageBox API
    ::MessageBoxW(GetSafeHwnd(), wszString, wszString, MB_OK);

    
//写文本同ansi to unicode
}



Ansi转换utf8和utf8转换Ansi就是上面2个的结合,把unicode作为中间量,进行2次转换即可
================
使用C++标准库的iostream,可以方便地将控制台、文件、字符串以及其它可扩充的外部表示作为流来处理,但要处理中文,却会碰到很多问题。 本人原来没怎么用过这个iostream,这几天尝试用这个写点东西,一会儿不能输出中文,一会儿不支持中文文件名的,搞得头大。网上搜了搜,没有发现适 用于所有情况的解决方案。不过后来自己经过多次测试,基本解决了这些问题,现在写成文字作为一个总结,也供碰到同样问题的朋友参考。关于C语言中的 printf和wprintf的中文输出,本文也进行了探讨。

  需要说明的是,我的开发环境是VS 2005(标准库当然也是微软实现的),不保证其它环境下是相同的效果。

1、cout和wcout

  在缺省的C locale下,cout可以直接输出中文,但对于wcout却不行(至少VS 2005下不行)。对于wcout,需要将其locale设为本地语言才能输出中文:

  wcout.imbue(locale(locale(),"",LC_CTYPE));  // ①

  也有人用如下语句的,但这会改变wcout的所有locale设置,比如数字“1234”会输出为“1,234”。

  wcout.imbue(locale(""));

2、ofstream和wofstream

   在缺省的C locale下,ofstream能正确输出中文到文件中,但不支持中文文件名;wofstream支持中文文件名,但不能向文件中输出中文。要解决这个 问题,需要在打开文件之前将全局locale设为本地语言。将全局locale设为本地语言后,ofstream和wofstream的问题都解决了,但 cout和wcout却不能输出中文了。要让cout和wcout输出中文,需要将全局locale恢复原来的设置,如下所示:

  locale &loc=locale::global(locale(locale(),"",LC_CTYPE));  // ②
  ofstream ofs("ofs测试.txt");
  wofstream wofs(L"wofs测试.txt");
  locale::global(loc);  // ③
  ofs<<"test测试"<<1234<<endl;
  wofs<<L"Another test还是测试"<<1234<<endl;

3、printf和wprintf

  加上这两位C语言中的老兄,问题更加复杂。考虑如下语句(注意s的大小写):

   printf("%s", "multibyte中文/n");  // ④
   printf("%S", L"unicode中文/n");  // ⑤
   wprintf(L"%S", "multibyte中文/n");  // ⑥
   wprintf(L"%s", L"unicode中文/n");  // ⑦

  缺省情况下,⑤、⑦两条语句不能输出中文,这两条语句中字符串的形式是unicode形式的。如果在所有输出语句之前加上如下语句将C语言的全局locale设置为本地语言(C语言中只有全局locale)就可以正常输出了:

  setlocale(LC_CTYPE, "");  // ⑧

  但这会导致cout和wcout不能输出中文(汗,的确麻烦),将C语言的全局locale恢复后cout和wcout就正常了,如下所示:

  setlocale(LC_CTYPE, "C");  // ⑨

   但恢复后,printf和wprintf输出Unicode文本又不正常了(输出MultiByte文本总是正常的)。总不能每写一个 printf/wprintf就设置一次然后再恢复一次吧?所以,建议不要混用iostream和printf/wprintf,实在要混用,那就让 printf/wprintf只输出MultiByte字符串,这样不需要调用setlocale(),也就不会影响到cout和wcout。

总结

  总之,用iostream、printf/wprintf输出中文,有点麻烦。概括起来要点如下:

  • 如果要用wcout,需要在使用之前按语句①将其locale设置为本地语言;
  • 如果要用ofstream或wofstream,要在打开文件之前按语句②将全局locale设为本地语言并保存初始的全局locale。然后在打开文件之后,按语句③将全局locale恢复为初始值;
  • 不要混用iostream和printf/wprintf。如果要混用,只用printf/wprintf输出MultiByte字符串;
  • 单独使用printf/wprintf时,如果要输出Unicode字符串,需要按语句⑧设置C语言的全局locale。如果只输出MultiByte字符串,则不需设置。
在wprintf()函数里面,调用了WideCharToMultiByte()函数,就是通过当前的Locale将Unicode的字符转换成本地字符。在不使用setlocale()的时候,wprintf()会使用默认的“C”locale判断给定的宽字符是否<255,如果大于255就返回错误,而不会进行显示。这也就是在没有setlocale()的情况下wprintf((wchar_t*)paName)不能显示的真正原因。我觉得,如果wprintf()不进行这种判断而直接将字符串给Console的话,就能够正确显示了


UTF-8转ANSI文本文件转换器 可批量将UTF-8的文本文件转为ANSI文本文件,代码略加修改,即可在换任意两种编码的文本文件内互相转化。 立即下载

相关推荐

utf-8 ansi 字符互转 工具

utf-8 ansi 字符互转 工具utf-8 ansi 字符互转 工具

【杂记】ANSI、ANSI编码、ASCII编码、ASCII控制字符、ANSI转义序列

(American National Standards Institute):美国国家标准协会。

无数_Mirage的博客 3563

电商平台大数据分析指标

一、五大关键数据分析指标 1.1活跃用户量 活跃用户量是一个基本的指标,有 DAU(日活跃用户)、WAU(周活跃用户)和 MAU(月活跃用户)三个层次; 1.2转化 转化是一个非常重要的指标,电商运营需要关注主路径、次路径甚至精细到每一个品类 / SKU 的转化率; 1.3留存 留存要从不同的时间周期上研究,包括次日留存率、3 日、7 日、30 日留存; 1.4复购 复购则要从 3 个角度去看,复购用户量、复购率和复购金额比; 1.5GMV GMV 是最重要的指标,我们的运营最终是围绕这

默主归沙的博客 4820

Spring转换编码utf-8方式

Spring转换编码utf-8方式 方式一:修改Spring配置文件(建议使用) &lt;mvc:annotation-driven&gt; &lt;mvc:message-converters register-defaults="true"&gt; &lt;bean class="org.springframewor...

weixin_42981419的博客 2122

新手必看!华为S5700交换机健康检查清单:从CPU到日志的完整巡检流程

本文为新手网管人员提供华为S5700交换机的健康检查完整指南,涵盖CPU、内存、温度、日志等核心指标的日常维护流程。通过详细的display命令和实用案例,帮助用户快速掌握设备体检技巧,确保交换机稳定运行。

weixin_29251337的博客 237

Endnote 导入参考文献的时候,格式错误太多了。et.al错误,国标GBT7714在endnote中的详细配置教程,适用于本科,硕士论文文献插入的模板

EndNote插入文献常遇到以下错误主要如下: 等、et al不分; 英文作者全名大写; 期刊名字使用了缩写(图片里没有体现;卷号、期号缺失时出现乱码,多了半个括号;页码范围略去了相同部分;没有悬挂缩进,本文全部解决,全网最细

sakura的博客 3万+

ANSI字符串和Unicode字符串

758

CentOS 7下Oracle 11G RAC静默安装避坑指南:从网络规划到共享存储配置全流程

本文详细介绍了在CentOS 7环境下进行Oracle 11G RAC静默安装的全流程,包括网络规划、共享存储配置和系统参数调优等关键步骤。特别针对静默安装过程中的常见问题提供了实用的避坑指南和优化建议,帮助技术人员高效完成企业级数据库部署。

weixin_29234509的博客 128

Ansi、Unicode、UTF8字符串之间的转换和写入文本文件

Ansi、Unicode、UTF8字符串之间的转换和写入文本文件 转载请注明出处http://www.cppblog.com/greatws/archive/2008/08/31/60546.html最近有人问我关于这个的问题,就此写一篇blogAnsi字符串我们最熟悉,英文占一个字节,汉字2个字节,以一个\0结尾,常用于txt文本文件Unicode字符串,每个字符(汉字、...

cpongo11的博客 629

wps js宏获取工作簿、工作表、单元格的值、链接转图片、单元格区域数据转二维数组、保存工作簿的常用Excel操作

wps js宏入门看这里,我写了常用的js操作Excel的方法:获取工作簿对象、获取工作表对象、获取单元格的值、链接转图片、生成条形码图片、单元格区域数据转二维数组方法、保存工作簿、弹出输入框、YesNo选择框,助你从VBA转战JS。

huaermeier的博客 3万+

Opencv2.4.9源码分析——HoughCircles

图形可以用一些参数进行表示,标准霍夫变换的原理就是把图像空间转换成参数空间(即霍夫空间),例如霍夫变换的直线检测就是在距离-角度空间内进行检测。圆可以表示成: (x-a)2+(y-b)2=r2                   (1) 其中a和b表示圆心坐标,r表示圆半径,因此霍夫变换的圆检测就是在这三个参数组成的三维空间内进行检测。 原则上,霍夫变换可以检测任何形状。但复杂的形状需要的

赵春江的专栏 3万+

Ansi、Unicode、UTF8字符串之间的转换,wprintf(学习)

Ansi字符串我们最熟悉,英文占一个字节,汉字2个字节,以一个/0结尾,常用于txt文本文件 Unicode字符串,每个字符(汉字、 英文字母)都占2个字节,以2个连续的/0结尾,NT操作系统内核用的是这种字符串,常被定义为typedef unsigned short wchar_t;所以我们有时常会见到什么char*无法转换为unsigned short*之类的错误,其实就是unicode

多媒体编程、网络编程、系统编程、网络安全编程、驱动编程 989

回归预测 | MATLAB实现SVR(支持向量机回归)K折交叉验证

回归预测 | MATLAB实现SVR(支持向量机回归)K折交叉验证 目录回归预测 | MATLAB实现SVR(支持向量机回归)K折交叉验证基本介绍划分原理留一划分交叉验证K折交叉数据下载程序设计参考资料致谢 基本介绍 在机器学习里,通常来说我们不能将全部用于数据训练模型,否则我们将没有数据集对该模型进行验证,从而评估我们的模型的预测效果。为了解决这一问题,有如下常用的方法: 第一种是最简单的,也是很容易就想到的。我们可以把整个数据集分成两部分,一部分用于训练,一部分用于验证,这也就是我们经常提到的训练集

机器学习之心的博客,关注并私信文章链接,获取对应文章源码和数据。 6377

C++中Ansi、Unicode、UTF8字符串之间的转换和写入文本文件

Ansi字符串我们最熟悉,英文占一个字节,汉字2个字节,以一个\0结尾,常用于txt文本文件 Unicode字符串,每个字符(汉字、英文字母)都占2个字节,以2个连续的\0结尾,NT操作系统内核用的是这种字符串,常被定义为typedef unsigned short wchar_t;所以我们有时常会见到什么char*无法转换为unsigned short*之类的错误,其实就是unicode U

记事本 4602

金融领域强化学习在高频交易中的应用

强化学习(Reinforcement Learning,简称RL)是一种机器学习范式,通过智能体与环境的交互来学习策略,以最大化累计奖励。与监督学习和无监督学习不同,强化学习依赖于动态的反馈机制,智能体通过试错不断优化决策过程。高频交易(High-Frequency Trading,简称HFT)是指在极短时间内进行的大量金融交易,通常利用算法和计算机系统自动执行交易策略。高频交易依赖于高速的数据处理和决策能力,以捕捉市场中的微小价格波动。状态(State):环境在某一时刻的观测,反映了系统的当前情况。

AI天才研究院 894

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

VC中Ansi、Unicode、UTF8字符串之间的转换和写入文本

VC中Ansi、Unicode、UTF8字符串之间的转换和写入文本 Ansi字符串我们最熟悉,英文占一个字节,汉字2个字节,以一个\0结尾,常用于txt文本文件 Unicode字符串,每个字符(汉字、英文字母)都占2个字节,以2个连续的\0结尾,NT操作系统内核用的是这种字符串,常被定义为typedef unsigned short wchar_t;所以我们有时常会见到什么char*无法转换为

Juey 3639

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

UFT-ASCII-GB2312-Unicode编码转换

最近有人问我关于这个的问题,就此写一篇blogAnsi字符串我们最熟悉,英文占一个字节,汉字2个字节,以一个/0结尾,常用于txt文本文件Unicode字符串,每个字符(汉字、英文字母)都占2个字节,以2个连续的/0结尾,NT操作系统内核用的是这种字符串,常被定义为typedef unsigned short wchar_t;所以我们有时常会见到什么char*无法转换为unsigned short

学无紫晶 2839

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

CFile针对不同格式(ANSI,UNICODE)的文档写操作方法

Ansi转Unicode 介绍2种方法 void CConvertDlg::OnBnClickedButtonAnsiToUnicode() {     // ansi to unicode     char* szAnsi = "abcd1234你我他";     //预转换,得到所需空间的大小     int wcsLen = ::MultiByteToWideChar(CP_ACP, NUL...

HHHUANG 1573

英文系统下unicode ansi utf8

一: 代码 1Ansi_1252_ToUnicode //Ansi_1252_ToUnicode void Ansi_1252_ToUnicode_By936() { char* szAnsi = "Äã"; //szAnsi=Äã int wcsLen = MultiByteToWideChar(936, NULL, szAnsi, strlen(szAnsi), NU...

jcair的博客 292
上一篇: 调试某驱动
下一篇: 突破卡巴7文件保护写文件
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值