UTF8与UniCode之间的相互转换

UTF8与UniCode之间的相互转换

这里不对两种编码进行官方的解释,如有不懂的可以自行百度。这里只对相互转换进行讨论。


UniCodeUTF8
00000000 - 0000007F0xxxxxxx
00000080 - 000007FF110xxxxx 10xxxxxx
00000800 - 0000FFFF1110xxxx 10xxxxxx 10xxxxxx
00010000 - 001FFFFF11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

此表是转换规则表,左边代表Unicode编码,右边代表utf8编码。将Unicode编码转换为二进后,根据它的范围填入UTF8对应的表中,不足的高位补0;

例子:UniCode转UTF8

Unicode:0000674E

UTF-8:E69D8E

  1. Unicode十六进制转二进制:0000674E->0110 0111 0100 1110
  2. 找出Unicode范围对应的UTF8编码:1110xxxx 10xxxxxx 10xxxxxx
  3. 将转换后的二进制从后往前代替UTF8编码中的X,不足高位 补0:11100110 10011101 10001110
  4. 转换好的二进制分别转成十六进制(按空格分割):E69D8E

UTF8转UniCode逆向操作就可以了,不再做描述

UniCode转UTF8代码

先说一下在编程中遇到的问题

  • wchar_t在Linux中是占4个字节的,但是在window中只占2个字节,导致UTF8编码有时候到3个字节了高位自动丢失了,随后换成了unsigned int占4个字节
  • 在参数传递中还是wchar_t类型,是因为Unicode编码是1-6个字节的,但是在转UTF8规则中没有超过2个字节的,就继续使用了
  • 换成unsigned int达到了目的,但是不知道怎么输出出来,一直输出的是十进制,于是改变方案,使用vector类型,这样解决了unsigned int不好输出的问题,又解决了wchar_t只占2个字节丢失数据的问题
  • 输出的时候需要修改CMD的编码格式,不然还是会乱码的
  • 代码中使用了大量的位运算符,如果对这些运算符不了解,阅读改代码比较困难
#include <iostream>
#include <vector>
#include <cstdio>

std::vector<unsigned char> uniCodeToUTF8(const wchar_t& wc)
{
    std::vector<unsigned char> utf8Str;
    //00-7F范围内
    if (wc <= 0X7F)
    {
        //添加到结果字符串中
        utf8Str.push_back(static_cast<char>(wc));
    }
    //80-7FF之间
    else if (wc <= 0X7FF)
    {   //高位
        utf8Str.push_back(static_cast<unsigned char>((wc >> 6) | 0XC0 & 0XDF));
    
        //低位
        utf8Str.push_back(static_cast<unsigned char>(wc & 0X3F | 0XC0 & 0XBF));
    }
    //800-FFFF之间
    else if (wc <= 0XFFFF)
    {
        utf8Str.push_back(static_cast<unsigned char>((wc >> 12) | 0XE0 & 0XEF));
        utf8Str.push_back(static_cast<unsigned char>((wc >> 6) & 0X3F | 0XC0 & 0XBF));
        utf8Str.push_back(static_cast<unsigned char>(wc & 0X3F | 0XC0 & 0XBF));
    }
    //10000-10FFFF之间
    else if (wc <= 0X10FFFF)
    {
        utf8Str.push_back(static_cast<unsigned char>((wc >> 18) | 0XF0 & 0XF7));
        utf8Str.push_back(static_cast<unsigned char>((wc >> 12) & 0X3F | 0XC0 & 0XBF));
        utf8Str.push_back(static_cast<unsigned char>((wc >> 6) & 0X3F | 0XC0 & 0XBF));
        utf8Str.push_back(static_cast<unsigned char>(wc & 0X3F | 0XC0 & 0XBF));
    }
    return utf8Str;
}

int main()
{
    wchar_t unicode = L'\u674E';
    std::vector<unsigned char> str = uniCodeToUTF8(unicode);
    str.push_back('\0');
    printf("%s\n",str.data());
}

UTF8转UniCode代码

先说一下在编程中遇到的问题

  • 可以看见我传入的是一个std::vector&,上面代码中写到wchar_t占用字节的问题,两边就都改成了unsigned int,但是这边并不存在输出,所以就没有修改
  • std::wstring是一个宽字符串,每一个占用2个字节,上面也提到了Unicode与UTF转换规则,2个字节就已经够用了
  • std::wcout 是专用与输出std::wstring和wchar_t的,但是不知道为什么输出不出来,这里建议写入文件再来观察;笔者是通过debug去观察的,转换没有问题就没有考虑输出了;主要是看转换的代码,重点并不是输出。
#include <iostream>
#include <vector>
std::wstring UTF8ToUnicode(const std::vector<unsigned int>& utf8)
{
	std::wstring uniCodeStr;
	for (unsigned int wc : utf8)
	{
		wchar_t temp = 0;
		//判断范围 高位是否为11110
		if (wc > 0XEFBFBF)
		{
			if ((wc >> 27) == 0X1E)
			{
				//满足条件,开始剥位
				temp = temp | ((wc >> 24) & 0X07);
				temp = (temp << 6) | ((wc >> 16) & 0X3F);
				temp = (temp << 6) | ((wc >> 8) & 0X3F);
				temp = (temp << 6) | (wc & 0x3F);
			}
		}
		//高位是否为1110
		else if (wc > 0XDFBF)
		{
			if ((wc >> 20) == 0x0E)
			{
				temp = temp | ((wc >> 16) & 0X0F);
				temp = (temp << 6) | ((wc >> 8) & 0X3F);
				temp = (temp << 6) | (wc & 0x3F);
			}
		}
		//高位是110
		else if (wc > 0X7F)
		{
			if ((wc >> 13) == 0X06)
			{
				temp = temp | ((wc >> 8) & 0X1F);
				temp = (temp << 6) | (wc & 0x3F);
			}
		}
		else
		{
			if ((wc >> 7) == 0X00)
			{
				temp = temp | (wc & 0X7F);
			}
		}
		uniCodeStr.push_back(static_cast<wchar_t>(temp));
	}
	return uniCodeStr;
}

int main()
{
	std::vector<unsigned int> utf8Str;
	utf8Str.push_back(0XE69D8E);
	std::wstring uniCodeStr =  UTF8ToUnicode(utf8Str);
	std::wcout << uniCodeStr << std::endl;
	return 0;
}
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是 Java 实现的 utf8,gbk,unicode 编码相互转换的代码: ```java import java.io.UnsupportedEncodingException; public class EncodingUtil { public static String utf8ToUnicode(String str) { try { byte[] bytes = str.getBytes("UTF-8"); StringBuilder builder = new StringBuilder(); for (int i = 0; i < bytes.length; i += 2) { builder.append("\\u"); String hexStr = Integer.toHexString(bytes[i + 1] & 0xff | (bytes[i] & 0xff) << 8); if (hexStr.length() == 2) { builder.append("00"); } builder.append(hexStr); } return builder.toString(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); return null; } } public static String unicodeToUtf8(String str) { StringBuilder builder = new StringBuilder(); int i = 0; while (i < str.length()) { if (str.charAt(i) == '\\' && str.charAt(i + 1) == 'u') { String hexStr = str.substring(i + 2, i + 6); int codePoint = Integer.parseInt(hexStr, 16); builder.append((char) codePoint); i += 6; } else { builder.append(str.charAt(i)); i++; } } try { return new String(builder.toString().getBytes("UTF-8"), "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); return null; } } public static String gbkToUtf8(String str) { try { return new String(str.getBytes("GBK"), "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); return null; } } public static String utf8ToGbk(String str) { try { return new String(str.getBytes("UTF-8"), "GBK"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); return null; } } public static String unicodeToGbk(String str) { return utf8ToGbk(unicodeToUtf8(str)); } public static String gbkToUnicode(String str) { return utf8ToUnicode(gbkToUtf8(str)); } } ``` 其中,`utf8ToUnicode` 方法将 utf8 编码的字符串转换unicode 编码的字符串,`unicodeToUtf8` 方法将 unicode 编码的字符串转换utf8 编码的字符串,`gbkToUtf8` 方法将 gbk 编码的字符串转换utf8 编码的字符串,`utf8ToGbk` 方法将 utf8 编码的字符串转换为 gbk 编码的字符串,`unicodeToGbk` 方法将 unicode 编码的字符串转换为 gbk 编码的字符串,`gbkToUnicode` 方法将 gbk 编码的字符串转换unicode 编码的字符串。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值