24,855
社区成员
发帖
与我相关
我的任务
分享
////////////////////////////////////////////////////////////////////////////////
//
// 文件名: UTF8.cpp
// 作者: 溪流
// 创建时间: 2009-1-22 20:25:02
// 描述: 编码转换。暂时只有 Unicode 转为 UTF-8 的功能。
//
////////////////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "Encoding.h"
////////////////////////////////////////////////////////////////////////////////
// UTF-8 定义:
// U-00000000 - U-0000007F: 0xxxxxxx
// U-00000080 - U-000007FF: 110xxxxx 10xxxxxx
// U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
// (以下是 UCS-4 了)
// U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
// U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
// U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
// 后面的 xxxx 用原来 Unicode 中的位依次填充
/// @brief Unicode 字符转换为 UTF-8 字符
/// @param buf [out] UTF-8 字符缓冲区,最大可能需要 6 个字节
/// @param bufSize buf 的大小,单位是字节
/// @param src [in] 源 Unicode 字符
/// @return 失败返回 -1,成功返回转换后 UTF-8 字符所占的字节数。
/// 如果缓冲区过小(bufSize 指示),则返回需要的字节数。
int CEncoding::WCharToUTF8(char *buf, int bufSize, const wchar_t src)
{
int bytesCount = 0;
wchar_t firstByte; // 从 Unicode 中取出二进制位作为 UTF-8 第一字节时的掩码
char utfFirstByte; // 为 UTF-8 第一字节加前导的若干个 1 要用的掩码
wchar_t wTmp;
char tmp;
if (src == 0)
{
return -1;
}
if (src <= 0x7f) // 01111111, ASCII
{
bytesCount = 1;
firstByte = 0x7f; // 0111 1111
utfFirstByte = (BYTE)0x00; // 0000 0000
}
else if (src <= 0x7ff) // 1000 0000 - 0111 1111 1111,有效位数 11 位
{
bytesCount = 2;
firstByte = 0x1f; // 0001 1111,除去后一字节的 6 位,还剩 5 位
utfFirstByte = (BYTE)0xc0; // 1100 0000
}
else if (src <= 0xffff) // 1000 0000 0000 - 1111 1111 1111 1111,16 位
{
bytesCount = 3;
firstByte = 0x0f; // 0000 1111,除去后两字节的 12 位,还剩 4 位
utfFirstByte = (BYTE)0xe0; // 1110 0000
}
// UCS-4 支持
else if (src <= 0x001fffff) // 计算方法下同,不再赘述
{
bytesCount = 4;
firstByte = 0x07;
utfFirstByte = (BYTE)0xf0;
}
else if (src <= 0x03ffffff)
{
bytesCount = 5;
firstByte = 0x03;
utfFirstByte = (BYTE)0xf8;
}
else if (src <= 0x7fffffff)
{
bytesCount = 6;
firstByte = 0x01;
utfFirstByte = (BYTE)0xfc;
}
// 提供的值不符合 Unicode 定义
else
{
return -1;
}
if (bufSize >= bytesCount)
{
wTmp = src;
for (int i = bytesCount - 1; i > 0; i--) // 从低位往高位处理
{
tmp = (char)(wTmp & 0x3f); // 取得低 6 位
buf[i] = tmp | 0x80; // 将最高 2 位变为 10
wTmp >>= 6;
}
// 后面若干字节都处理完了,现在处理第一个字节
tmp = (char)(wTmp & firstByte); // 取出源字符中的剩余若干位
buf[0] = (tmp | utfFirstByte); // 高位或上若干个 1
}
return bytesCount;
}
/// @brief 字符转换为 UTF-8 字符
/// @param buf [out] UTF-8 字符串缓冲区
/// @param bufSize buf 的大小,单位是字节
/// @param src [in] 源 Unicode 字符串
/// @return 返回转换后 UTF-8 字符串所占的字节数。如果缓冲区过小(bufSize 指示),
/// 那么仅转换到前 bufSize -1 个字节,第 bufSize 字节填零,返回 bufSize。
/// 可以用根据返回值是否小于原来提供的 bufSize 来判断缓冲区是否足够大。
int CEncoding::WCharStringToUTF8(char *buf, int bufSize, wchar_t *src)
{
int i = 0;
while (*src != 0)
{
if (i >= bufSize)
{
buf[i - 1] = '\0';
return i;
}
i += CEncoding::WCharToUTF8(buf + i, bufSize - i, *src++);
}
buf[i] = '\0';
return i;
}
////////////////////////////////////////////////////////////////////////////////
//LPCSTR pASCIIBuf 要转换的ascii字符串指针
//LPSTR pUtf8Buf=NULL 转换成Utf8编码的字符串指针
//返回值 如果pUtf8Buf为0 则返回需要pUtf8Buf长度
int AToUtf8(LPCSTR pASCIIBuf,LPSTR pUtf8Buf=NULL)
{
if (NULL==pASCIIBuf)
return 0;
// ZeroMemory( wch, sizeof(WCHAR)*RECV_BUF );
DWORD UniCodeLen=MultiByteToWideChar(CP_ACP, 0, pASCIIBuf, -1, 0, 0);
AUTO_NEW(wch,unsigned short,UniCodeLen);
MultiByteToWideChar(CP_ACP, 0, pASCIIBuf, -1, wch, UniCodeLen);
DWORD dwUtf8Len=WideCharToMultiByte(CP_UTF8, 0, wch, UniCodeLen , NULL, NULL, NULL, NULL );
if (NULL==pUtf8Buf)
return dwUtf8Len;
return WideCharToMultiByte(CP_UTF8, 0, wch, UniCodeLen , pUtf8Buf, dwUtf8Len, NULL, NULL );
}