字符编码(ANSI,UTF-8,BINCODE)

来源:互联网 发布:中国海军 知乎 编辑:程序博客网 时间:2024/06/10 03:47

有三种编码方式和三种字符类型。
  第一种编码方式是单字节字符集,称之为SBCS,它的所有字符都只有一个字节的长度。ASCII码就是SBCS。SBCS字符串由一个零字节结尾。
  第二种编码方式是多字节字符集,称之为MBCS,它包含的字符中有单字节长的字符,也有多字节长的字符。Windows用到的MBCS只有二种字符类型,单字节字符和双字节字符。因此

Windows中用得最多的字符是双字节字符集,即DBCS,通常用它来代替MBCS。
  在DBCS编码中,用一些保留值来指明该字符属于双字节字符。例如,Shift-JIS(通用日语)编码中,值0x81-0x9F 和 0xE0-0xFC 的意思是:“这是一个双字节字符,下一个字节是这个字

符的一部分”。这样的值通常称为前导字节(lead byte),总是大于0x7F。前导字节后面是跟随字节(trail byte)。DBCS的跟随字节可以是任何非零值。与SBCS一样,DBCS字符串也由一个零字

节结尾。
  第三种编码方式是Unicode。 Unicode编码标准中的所有字符都是双字节长。有时也将Unicode称为宽字符集(wide characters),因为它的字符比单字节字符更宽(使用更多内存)。注意,

Unicode不是MBCS - 区别在于MBCS编码中的字符长度是不同的。Unicode字符串用二个零字节字符结尾(一个宽字符的零值编码)。
  单字节字符集是拉丁字母,重音文字,用ASCII标准定义,用于DOS操作系统。
    双字节字符集用于东亚和中东语言。
    Unicode用于COM和Windows NT内部。
  读者都很熟悉单字节字符集,它的数据类型是char。
    双字节字符集也使用char数据类型(双字节字符集中的许多古怪处之一)。
    Unicode字符集用wchar_t数据类型。Unicode字符串用L前缀起头,如:

wchar_t wch = L'1';      // 2 个字节, 0x0031

wchar_t* wsz = L"Hello"; // 12 个字节, 6 个宽字符

代码页(Code Page)是个古老的专业术语,据说是IBM公司首先使用的。代码页和字符集的含义基本相同,代码页规定了适用于特定地区的字符集合,和这些字符的编码。可以将代码页理解

为字符和字节数据的映射表。
  Windows为自己支持的代码页都编了一个号码。例如代码页936就是简体中文 GBK,代码页950就是繁体中文 Big5。代码页的概念比较简单,就是一个字符编码方案。但要说清楚Windows的

ANSI代码页,就要从Windows的区域(Locale)说起了。


转换:
//将单字节char*转化为宽字节wchar_t*
wchar_t* AnsiToUnicode( const char* szStr )
{
    int nLen = MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, szStr, -1, NULL, 0 );
    if (nLen == 0)
    {
 return NULL;
    }
    wchar_t* pResult = new wchar_t[nLen];
    MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, szStr, -1, pResult, nLen );
    return pResult;
}

//将宽字节wchar_t*转化为单字节char*
char* UnicodeToAnsi( const wchar_t* szStr )
{
    int nLen = WideCharToMultiByte( CP_ACP, 0, szStr, -1, NULL, 0, NULL, NULL );
    if (nLen == 0)
    {
        return NULL;
    }
    char* pResult = new char[nLen];
    WideCharToMultiByte( CP_ACP, 0, szStr, -1, pResult, nLen, NULL, NULL );
    return pResult;
}


wstring StringToWString(const string& str)     
{     
    wstring result;     
    //获取缓冲区大小,并申请空间,缓冲区大小按字符计算     
    int len = MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.size(), NULL, 0);     
    wchar_t* buffer = new wchar_t[len + 1];     
    //多字节编码转换成宽字节编码     
    MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.size(), buffer, len);     
    buffer[len] = '/0';             //添加字符串结尾     
    //删除缓冲区并返回值     
    result.append(buffer);     
    delete[] buffer;     
    return result;     
}     


string WstringToString(const wstring& wstr)     
{     
    string result;     
    //获取缓冲区大小,并申请空间,缓冲区大小事按字节计算的     
    int len = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), wstr.size(), NULL, 0, NULL, NULL);     
    char* buffer = new char[len + 1];     
    //宽字节编码转换成多字节编码     
    WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), wstr.size(), buffer, len, NULL, NULL);     
    buffer[len] = '/0';     
    //删除缓冲区并返回值     
    result.append(buffer);     
    delete[] buffer;     
    return result;     


// UTF-8转UNICODE
wchar_t* Utf8ToUnicode(const char* buf)
{
    int len = MultiByteToWideChar(CP_UTF8, 0, buf, -1, NULL, 0);
    if (len == 0) return L"";
 
    wchar_t* pResult = new wchar_t[len];
    MultiByteToWideChar( CP_UTF8, 0, buf, -1, pResult, len );
    return pResult;
}

// UNICODE转UNT-8
char* UnicodeToUtf8(const wchar_t* buf)
{
    int len = WideCharToMultiByte(CP_UTF8, 0, buf, -1, NULL, 0, NULL, NULL);
    if (len == 0) return "";
 
    char* pResult = new char[len];
    WideCharToMultiByte( CP_UTF8, 0, buf, -1, pResult, len, NULL, NULL );
    return pResult;
}