首页 > 代码库 > C++ UTF8和UTF16互转代码
C++ UTF8和UTF16互转代码
简介
1、这段代码只考虑在小端序情况下的转换(一般的机器都是的)。
2、这段代码需要C++11的支持(只是用到了u16string
),如果不支持,可以添加下面代码
typedef uint16_t char16_t;typedef std::basic_string<char16_t>
utfconvert.h
#ifndef __UTFCONVERT_H__#define __UTFCONVERT_H__#include <string>// 从UTF16编码字符串构建,需要带BOM标记std::string utf16_to_utf8(const std::u16string& u16str);// 从UTF16 LE编码的字符串创建std::string utf16le_to_utf8(const std::u16string& u16str);// 从UTF16BE编码字符串创建std::string utf16be_to_utf8(const std::u16string& u16str);// 获取转换为UTF-16 LE编码的字符串std::u16string utf8_to_utf16le(const std::string& u8str, bool addbom = false, bool* ok = NULL);// 获取转换为UTF-16 BE的字符串std::u16string utf8_to_utf16be(const std::string& u8str, bool addbom = false, bool* ok = NULL);#endif //! __UTFCONVERT_H__
utfconvert.cpp
#include "utfconvert.h"#include <stdint.h>#ifdef __GNUC__#include <endian.h>#endif // __GNUC__static inline uint16_t byteswap_ushort(uint16_t number){#if defined(_MSC_VER) && _MSC_VER > 1310 return _byteswap_ushort(number);#elif defined(__GNUC__) return __builtin_bswap16(number);#else return (number >> 8) | (number << 8);#endif}////////////////////////////////////////// 以下转换都是在小端序下进行 //////////////////////////////////////////// 从UTF16编码字符串构建,需要带BOM标记std::string utf16_to_utf8(const std::u16string& u16str){ if (u16str.empty()){ return std::string(); } //Byte Order Mark char16_t bom = u16str[0]; switch (bom){ case 0xFEFF: //Little Endian return utf16le_to_utf8(u16str); break; case 0xFFFE: //Big Endian return utf16be_to_utf8(u16str); break; default: return std::string(); }}// 从UTF16 LE编码的字符串创建std::string utf16le_to_utf8(const std::u16string& u16str){ if (u16str.empty()){ return std::string(); } const char16_t* p = u16str.data(); std::u16string::size_type len = u16str.length(); if (p[0] == 0xFEFF){ p += 1; //带有bom标记,后移 len -= 1; } // 开始转换 std::string u8str; u8str.reserve(len * 3); char16_t u16char; for (std::u16string::size_type i = 0; i < len; ++i){ // 这里假设是在小端序下(大端序不适用) u16char = p[i]; // 1字节表示部分 if (u16char < 0x0080){ // u16char <= 0x007f // U- 0000 0000 ~ 0000 07ff : 0xxx xxxx u8str.push_back((char)(u16char & 0x00FF)); // 取低8bit continue; } // 2 字节能表示部分 if (u16char >= 0x0080 && u16char <= 0x07FF){ // * U-00000080 - U-000007FF: 110xxxxx 10xxxxxx u8str.push_back((char)(((u16char >> 6) & 0x1F) | 0xC0)); u8str.push_back((char)((u16char & 0x3F) | 0x80)); continue; } // 代理项对部分(4字节表示) if (u16char >= 0xD800 && u16char <= 0xDBFF) { // * U-00010000 - U-001FFFFF: 1111 0xxx 10xxxxxx 10xxxxxx 10xxxxxx uint32_t highSur = u16char; uint32_t lowSur = p[++i]; // 从代理项对到UNICODE代码点转换 // 1、从高代理项减去0xD800,获取有效10bit // 2、从低代理项减去0xDC00,获取有效10bit // 3、加上0x10000,获取UNICODE代码点值 uint32_t codePoint = highSur - 0xD800; codePoint <<= 10; codePoint |= lowSur - 0xDC00; codePoint += 0x10000; // 转为4字节UTF8编码表示 u8str.push_back((char)((codePoint >> 18) | 0xF0)); u8str.push_back((char)(((codePoint >> 12) & 0x3F) | 0x80)); u8str.push_back((char)(((codePoint >> 06) & 0x3F) | 0x80)); u8str.push_back((char)((codePoint & 0x3F) | 0x80)); continue; } // 3 字节表示部分 {