转载请注明出处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. mysql5.7 数据库自动备份脚本

    新建备份目录 mkdir /backups mkdir /backups/mysql 新建存放备份脚本目录 mkdir /data/scripts 备份脚本: mysql_backup.sh ==== ...

  2. Python for Data Analysis 学习心得(一) - numpy介绍

    一.简介 Python for Data Analysis这本书的特点是将numpy和pandas这两个工具介绍的很详细,这两个工具是使用Python做数据分析非常重要的一环,numpy主要是做矩阵的 ...

  3. 用积分方法求K次方和数列公式

    这是我很早以前在高中时发现的一个通用计算K次方和数列公式的方法,很特别的地方是用了微积分中的积分方法.目前我还没有发现有谁提出和我一样的方法,如果哪位读者有相关发现,麻烦告知我. 大家很多人都知道高斯 ...

  4. AntDesign getFieldDecorator 获取自定义组件的值

    AntDesign getFieldDecorator 获取自定义组件的值 1.自定义或第三方的表单控件,也可以与 Form 组件一起使用.只要该组件遵循以下的约定: (1)提供受控属性 value ...

  5. 详解Spring IoC容器

    一.Spring IoC容器概述 1.依赖反转(依赖注入):依赖对象的获得被反转了. 如果合作对象的引用或依赖关系的管理由具体对象来完成,会导致代码的高度耦合和可测试性的降低,这对复杂的面向对象系统的 ...

  6. ThreadLocal解析:父线程的本地变量不能传递到子线程详解

    众所周知,ThreadLocal类是java提供线程本地变量的工具类.但父线程的本地变量却不能被子线程使用,代码如下: public static void main(String[] args) { ...

  7. Spark学习笔记(三)—— Standalone模式

    上篇笔记记录了Local模式的一些内容,但是实际的应用中很少有使用Local模式的,只是为了我们方便学习和测试.真实的生产环境中,Standalone模式更加合适一点. 1.基础概述 Standalo ...

  8. 《C++Primer》第五版习题答案--第三章【学习笔记】

    [C++Primer]第五版[学习笔记]习题解答第三章 ps:答案是个人在学习过程中书写,可能存在错漏之处,仅作参考. 作者:cosefy Date: 2020/1/10 第三章:字符串,向量和数组 ...

  9. java架构之路(多线程)synchronized详解以及锁的膨胀升级过程

    上几次博客,我们把volatile基本都说完了,剩下的还有我们的synchronized,还有我们的AQS,这次博客我来说一下synchronized的使用和原理. synchronized是jvm内 ...

  10. 四、JVM之栈与栈帧

    栈: 1.又名堆栈,它是一种运算受限的线性表.其限制是仅允许在表的一端进行插入和删除运算.这一端被称为栈顶,相对地,把 另一端称为栈底.其特性是先进后出. 2.栈是线程私有的,生命周期跟线程相同,当创 ...