转载请注明出处http://www.cppblog.com/greatws/archive/2008/08/31/60546.html



最近有人问我关于这个的问题,就此写一篇blog



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次转换即可

UTF-8转ANSI的方法
void ConvertUTF8ToANSI(char* strUTF8,CString &strANSI) //
{
int nLen = ::MultiByteToWideChar(CP_UTF8,MB_ERR_INVALID_CHARS,(LPCTSTR)strUTF8,-1,NULL,0);
//返回需要的unicode长度
WCHAR * wszANSI = new WCHAR[nLen+1];
memset(wszANSI, 0, nLen * 2 + 2);
nLen = MultiByteToWideChar(CP_UTF8, 0, (LPCTSTR)strUTF8, -1, wszANSI, nLen); //把utf8转成unicode
nLen = WideCharToMultiByte(CP_ACP, 0, wszANSI, -1, NULL, 0, NULL, NULL); //得到要的ansi长度
char *szANSI=new char[nLen + 1];
memset(szANSI, 0, nLen + 1);
WideCharToMultiByte (CP_ACP, 0, wszANSI, -1, szANSI, nLen, NULL,NULL); //把unicode转成ansi
strANSI = szANSI;
delete wszANSI;
delete szANSI;
}

Ansi、Unicode、UTF8字符串之间的转换和写入文本文件的更多相关文章

  1. Perl中文/unicode/utf8/GB2312之间的转换

    参考:http://daimajishu.iteye.com/blog/959239不过具测试,也有错误:原文如下: # author: jiangyujieuse utf8;  ##在最后一个例子, ...

  2. 各种字符编码方式详解及由来(ANSI,UNICODE,UTF-8,GB2312,GBK)

    一直对字符的各种编码方式懵懵懂懂,什么ANSI UNICODE UTF-8 GB2312 GBK DBCS UCS……是不是看的很晕,假如您细细的阅读本文你一定可以清晰的理解他们.Let's go! ...

  3. json对象和json字符串之间的转换-JavaScript实现

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  4. python中unicode, hex, bin之间的转换

    python中unicode, hex, bin之间的转换 背景 在smb中有个feature change notify, 需要改动文件权限dacl,然后确认是否有收到notify.一直得不到这个d ...

  5. Java基础——基本类型和包装类、基本类型和字符串之间的转换

    基本类型和包装类之间的转换 基本类型和包装类之间经常需要互相转换,以 Integer 为例(其他几个包装类的操作雷同哦): 在 JDK1.5 引入自动装箱和拆箱的机制后,包装类和基本类型之间的转换就更 ...

  6. C++中数字与字符串之间的转换,别人的,

    C++中数字与字符串之间的转换   1.字符串数字之间的转换 (1)string --> char *   string str("OK");   char * p = st ...

  7. Java 中基本类型和字符串之间的转换

    Java 中基本类型和字符串之间的转换 在程序开发中,我们经常需要在基本数据类型和字符串之间进行转换. 其中,基本类型转换为字符串有三种方法: 1. 使用包装类的 toString() 方法 2. 使 ...

  8. JavaSE(六)包装类、基本类型和字符串之间的转换、==和equals的区别

    一.包装类 Java语言是一个面向对象的语言,但是Java中的基本数据类型却是不面向对象的,这在实际使用时存在很多的不便,为了解决这个不足, 在设计类时为每个基本数据类型设计了一个对应的类进行代表,这 ...

  9. SQL Server 取日期时间格式 日期与字符串之间的转换

    SQL Server 取日期时间部分   在本文中,GetDate()获得的日期由两部分组成,分别是今天的日期和当时的时间: Select GetDate()  用DateName()就可以获得相应的 ...

随机推荐

  1. 使用Theia——构建你自己的IDE

    上一篇:Theia架构 构建你自己的IDE 本指南将教你如何构建你自己的Theia应用. 必要条件 你需要安装node 10版本(译者:事实上最新的node稳定版即可): curl -o- https ...

  2. day4(dict和set)

    dict 内置字典,使用key-value存储,具有极快的查找速度. >>>d = {'michael': 95, 'bob': 75, 'tracy': 85} >>& ...

  3. [ASP.NET Core 3框架揭秘] Options[1]: 配置选项的正确使用方式[上篇]

    依赖注入不仅是支撑整个ASP.NET Core框架的基石,也是开发ASP.NET Core应用采用的基本编程模式,所以依赖注入十分重要.依赖注入使我们可以将依赖的功能定义成服务,最终以一种松耦合的形式 ...

  4. Go指针,如此轻松掌握,希望有收获

    开篇语 依稀记得大学必修课,C语言中的指针,简直是噩梦,指来指去,有没有晕乎乎的感觉,我在想是不是也因为如此,所以Java语言的开发者C才比C语言的多,Java正因为解决了C的痛点,所以今天才能变成语 ...

  5. CF854C Planning优先队列|set

    C. Planning 传送门 Helen works in Metropolis airport. She is responsible for creating a departure sched ...

  6. Spring Cloud 如何动态刷新 Git 仓库配置?

    有时候在配置中心有些参数是需要修改的,这时候如何不重启而达到实时生效的效果呢? 本文基于以下讲解: Spring Cloud Greenwich.SR3 Spring Boot 2.1.7.RELEA ...

  7. ubuntu pycharm、idea创建快捷方式

    编辑/usr/share/application/pycharm.desktop [Desktop Entry] Type=Application Name=Pycharm GenericName=P ...

  8. 倍增LCA模板2董博文版 伪代码

    Dfs(int rt){ f[][rt]; ;k<=;k++) f[k][rt]=f[k-][f[k-][rt]]; } int LCA(int x,int y){ if(Dp[x]<Dp ...

  9. Windows安装Python环境和Python集成开发环境(IDE)PyCharm

    1.Windows中安装Python 3 (1)打开浏览器,访问Python官网(https://www.python.org/) (2)光标移动至Downloads,单机Windows链接 (3)根 ...

  10. T117897 七步洗手法 / PJT1(洛谷)

    题目:现在有n个人需要依次使用1个洗手池洗手,进行一步洗手需要1单位时间.他们每个人至少会进行一步洗手,但是却不一定进行了完整的七部洗手. 现在你知道了他们总共的洗手时间为t,请你推测他们有多少人进行 ...