精华内容
下载资源
问答
  • 使用CString在UTF8和UTF16之间转换。
  • utf16<=> utf8 <=> ascii <=>unicode 所有代码都已经经过验证。而且里面也有相应的例子。 所有的编码格式进行转换,windows平台。
  • UTF8 UTF16 Unicode逐字分割 支持emoji字节集
  • UTF-8 相互转换 UTF16

    2017-06-20 11:37:23
    UTF-8 相互转换 UTF16
  • 1.支持文件读入UTF-16、32文本格式数据,并相互转换 2.支持并将转换完的数据保存到文件
  • 将UTF8转换为UTF16。 UTF8.js 由。 浏览器和NW.js(node-webkit) < script src = "<module> < / script > < script src = "<module> < / script > < script > var source = "\u3042\u3044\u...
  • 收藏的基于C编写的utf8<->unicode和utf16<->unicode相互之间的转换。
  • tinyxml - utf16.cpp

    2020-05-06 15:04:54
    UTF=16LE编码方式保存或读取文件,可以结合博客“c++ 以UTF-16LE编码方式保存文件”查看辅助理解
  • UTF8-无BOM转为UTF16LE

    2013-05-30 09:09:12
    基于C写的 UTF8-无BOM转为UTF16LE UTF8-无BOM转为UTF8 UTF8转为UTF8-无BOM
  • 一些文件是uff16格式,虽然也是文本类型文件,但读取总是出现乱码,因此写了一个程序,可实现对UTF16编码的文件转换为utf8编码文件,请大家下载之前查清楚自己遇到的文件是否是utf16格式的.否则无效哦.使用方法请打开脚本...
  • UTF16 UTF-16 UTF16BE UTF-16BE UTF16LE UTF-16LE UTF32 UTF-32 UTF32BE UTF-32BE UTF32LE UTF-32LE UCS2 UCS-2 UCS-2LE UCS-2BE UCS-2-INTERNAL UCS4 UCS-4 UCS-4LE UCS-4BE UCS-4-INTERNAL ...
  • const-utf16可在 const 上下文中使用的 utf8 到 utf16 转换函数。用const HELLO_WORLD_UTF16:& [u16 ]= const_utf16::encode! ("Hello, world!" );最低支持 Rust 版本 (MSRV)由于使用了一些 const 表达式功能,...
  • UTF8、UTF16、UTF32区别

    千次阅读 2019-04-10 22:19:30
    UTF8、UTF16、UTF32区别

    UTF8、UTF16、UTF32都是unicode字符集的字符编码。

    UTF意思是unicode转换格式(Unicode transform format),出现UTF8、UTF16、UTF32是出于要在内存中存储字符的目的而对unicode字符编号进行编码。

    UTF8、UTF16、UTF32区别:(8、16、32可看做每种字符编码存储所需的最少的比特位数)

    UTF8:存在单字节编码,兼容ASCII;当编码为一个字节,则设最高比特位为0;当编码超过一个字节,则需要几个字节,就在第一个字节从最高位开始令连续的几个比特位为1,之后的字节最高位为10。

    UTF32:用固定长度的字节存储字符编码,不管Unicode字符编号需要几个字节,全部都用4个字节存储,直接存储Unicode编号。无需经过字符编号向字符编码的转换步骤,提高效率,用空间换时间。

    UTF16:使用2或4个字节进行存储。对于Unicode编号范围在0~FFFF之间的字符,统一用两个字节存储,无需字符转换,直接存储Unicode编号。对于Unicode字符编号在10000-10FFFF之间的字符,UTF16用四个字节存储,简单说就是:将Unicode字符编号(3字节)分为两部分,高位部分(Unicode字符编号中占1.5个字节)用一个值介于 D800-DBFF (110110yy yyyyyyyy,y为0/1)之间的双字节存储,低位部分用一个值介于 DC00-DFFF (110111xx xxxxxxxx,x为0/1)的双字节存储。而介于D800-DFFF之间的编码在Unicode中是预留的,不安排字符,如果Unicode中有字符的编号是这之间的值,会引发冲突和歧义,很有可能一个不常见字符(存储为四个字节)最后被读成两个常见字符(存储为两个字节)。

    参考:https://blog.csdn.net/pipi1375/article/details/84784392

    展开全文
  • Go语言---unicode/utf8 unicode/utf16

    千次阅读 2018-05-10 11:22:10
    unicode/utf8包utf8实现了函数和常量来支持UTF-8编码的文本。它包括在runes和UTF-8字节序列之间转换的函数。utf8里面的函数就有一些字节和字符的转换。//判断是否符合UTF编码的函数 // Valid 判断 p 是否为完整有效...

    unicode/utf8

    包utf8实现了函数和常量来支持UTF-8编码的文本。它包括在runes和UTF-8字节序列之间转换的函数。

    utf8里面的函数就有一些字节和字符的转换。

    //判断是否符合UTF编码的函数
    // Valid 判断 p 是否为完整有效的 UTF8 编码序列。
    func Valid(p []byte) bool
    // ValidRune 判断 r 能否被正确的转换为 UTF8 编码
    // 超出 Unicode 范围的码点或 UTF-16 代理区中的码点是不能转换的
    func ValidRune(r rune) bool
    // 参数是字符串
    func ValidString(s string) bool

    unicode字符编码范围:

    unicode 字节位表
    unicode 编码范围 十进制/十六进制
    UTF-8 字节模板二进制/十六进制
    字节数
    
    一字节
    (0)000000 – (127)00007F 
    0xxxxxxx(00-7F)
    
    两个字节
    (128)000080 – (2047)0007FF 
    110xxxxx(C2-DF)      10xxxxxx
    
    三个字节
    (2048)000800 – (55295)00D7FF (57344)00E000 – (65535)00FFFF 
    1110xxxx(E0-EF)     10xxxxxx     10xxxxxx
    
    四个字节
    (65536)010000 – (1114111)10FFFF 
    11110xxx(F0-F4) 10xxxxxx 10xxxxxx 10xxxxxx

    程序示例:

    //由 main 函数作为程序入口点启动
    func main(){
    	valid1 := []byte("Hello, 世界")
    	invalid1 := []byte{0xff, 0xfe, 0xfd}
    
    	fmt.Println(utf8.Valid(valid1))        // true
    	fmt.Println(utf8.Valid(invalid1))      // false
    
    	valid2 := 'a'
    	invalid2 := rune(0xfffffff)
    
    	fmt.Println(utf8.ValidRune(valid2))    // true
    	fmt.Println(utf8.ValidRune(invalid2))  // false
    
    	valid3 := "Hello, 世界"
    	invalid3 := string([]byte{0xff, 0xfe, 0xfd})
    
    	fmt.Println(utf8.ValidString(valid3))   // true
    	fmt.Println(utf8.ValidString(invalid3)) // false
    
    	b := []byte("你好")
    	fmt.Printf("%t, ", utf8.Valid(b))     // true
    	fmt.Printf("%t, ", utf8.Valid(b[1:])) // false
    	fmt.Printf("%t, ", utf8.Valid(b[2:])) // false
    	fmt.Printf("%t, ", utf8.Valid(b[:2])) // false
    	fmt.Printf("%t, ", utf8.Valid(b[:1])) // false
    	fmt.Printf("%t\n", utf8.Valid(b[3:])) // true
    
    	fmt.Printf("%t, ", utf8.ValidRune('好'))        // true
    	fmt.Printf("%t, ", utf8.ValidRune(0))          // true
    	fmt.Printf("%t, ", utf8.ValidRune(0xD800))     // false  代理区字符
    	fmt.Printf("%t\n", utf8.ValidRune(0x10FFFFFF)) // false  超出范围
    }
    // FullRune 检测 p 中第一个字符的 UTF-8 编码是否完整(完整并不表示有效)。
    // 一个无效的编码也被认为是完整字符,因为它将被转换为一个 RuneError 字符。
    // 只有“编码有效但长度不够”的字符才被认为是不完整字符。
    // 也就是说,只有截去一个有效字符的一个或多个尾部字节,该字符才算是不完整字符。
    // 举例:
    // "好"     是完整字符
    // "好"[1:] 是完整字符(首字节无效,可转换为 RuneError 字符)
    // "好"[2:] 是完整字符(首字节无效,可转换为 RuneError 字符)
    // "好"[:2] 是不完整字符(编码有效但长度不够)
    // "好"[:1] 是不完整字符(编码有效但长度不够)
    func FullRune(p []byte) bool
    
    // 功能同上,参数为字符串
    func FullRuneInString(s string) bool
    
    // 返回 p 中的字符个数
    // 错误的 UTF8 编码和长度不足的 UTF8 编码将被当作单字节的 RuneError 处理
    func RuneCount(p []byte) int
    
    // 功能同上,参数为字符串
    func RuneCountInString(s string) (n int)
    
    // RuneLen 返回需要多少字节来编码字符 r,如果 r 是无效的字符,则返回 -1
    func RuneLen(r rune) int
    
    // 判断 b 是否为 UTF8 字符的首字节编码,最高位(bit)是不是 10 的字节就是首字节。
    func RuneStart(b byte) bool

    程序示例:

    func main(){
    	b := []byte("好")
    	fmt.Printf("%t, ", utf8.FullRune(b))     // true
    	fmt.Printf("%t, ", utf8.FullRune(b[1:])) // true
    	fmt.Printf("%t, ", utf8.FullRune(b[2:])) // true
    	fmt.Printf("%t, ", utf8.FullRune(b[:2])) // false
    	fmt.Printf("%t\n", utf8.FullRune(b[:1])) // false
    
    	str := "世"
    	fmt.Println(utf8.FullRuneInString(str))     //true
    	fmt.Println(utf8.FullRuneInString(str[:2])) //false
    
    	b = []byte("大家好")
    	fmt.Println(utf8.RuneCount(b)) // 3
    
    	fmt.Printf("%d, ", utf8.RuneLen('A'))          // 1
    	fmt.Printf("%d, ", utf8.RuneLen('\u03A6'))     // 2
    	fmt.Printf("%d, ", utf8.RuneLen('好'))          // 3
    	fmt.Printf("%d, ", utf8.RuneLen('\U0010FFFF')) // 4
    	fmt.Printf("%d\n", utf8.RuneLen(0x1FFFFFFF))   // -1
    
    	fmt.Printf("%t, ", utf8.RuneStart("好"[0])) // true
    	fmt.Printf("%t, ", utf8.RuneStart("好"[1])) // false
    	fmt.Printf("%t\n", utf8.RuneStart("好"[2])) // false
    }

    程序示例:

    //由 main 函数作为程序入口点启动
    func main(){
    	r := '世'
    	buf := make([]byte, 3)
    	n := utf8.EncodeRune(buf, r)
    	fmt.Println(buf)
    	fmt.Println(n)
    
    	b := []byte("Hello, 世界")
    	for len(b) > 0 {
    		r, size := utf8.DecodeRune(b)    //解码 p 中的第一个字符,返回解码后的字符和 p 中被解码的字节数
    		fmt.Printf("%c %v\n", r, size)
    
    		b = b[size:]
    	}
    
    	str := "Hello, 世界"
    
    	for len(str) > 0 {
    		r, size := utf8.DecodeRuneInString(str)
    		fmt.Printf("%c %v\n", r, size)
    
    		str = str[size:]
    	}
    
    	b := []byte("Hello, 世界")
    	for len(b) > 0 {
    		r, size := utf8.DecodeLastRune(b)
    		fmt.Printf("%c %v\n", r, size)
    
    		b = b[:len(b)-size]
    	}
    }

    unicode/utf16

    // IsSurrogate 判断 r 是否为代理区字符
    // 两个代理区字符可以用来组合成一个 utf16 编码
    func IsSurrogate(r rune) bool
    
    // EncodeRune 将字符 r 编码成 UTF-16 代理对
    // r:要编码的字符
    // 如果 r < 0x10000 ,则无需编码,其 UTF-16 序列就是其自身
    // r1:编码后的 UTF-16 代理对的高位码元
    // r2:编码后的 UTF-16 代理对的低位码元
    // 如果 r 不是有效的 Unicode 字符,或者是代理区字符,或者无需编码
    // 则返回 U+FFFD, U+FFFD
    func EncodeRune(r rune) (r1, r2 rune)
    
    // DecodeRune 将 UTF-16 代理对解码成一个 Unicode 字符
    // r1:是 UTF-16 代理对的高位码元
    // r2:是 UTF-16 代理对的低位码元
    // 返回值为解码后的 Unicode 字符
    // 如果 r1 或 r2 不是有效的 UTF-16 代理区字符,则返回 U+FFFD
    func DecodeRune(r1, r2 rune) rune
    
    // Decode 将 UTF-16 序列 s 解码成 Unicode 字符序列并返回
    func Decode(s []uint16) []rune
    
    // Encode 将 s 编码成 UTF-16 序列并返回
    func Encode(s []rune) []uint16

    相对来说,utf-16编码格式使用较少。

    参考博客:http://www.cnblogs.com/golove/p/3272007.html

                    https://golang.org/pkg/unicode/utf16/#IsSurrogate   官网资料

    展开全文
  • 将UTF8编码格式的文件转换编码到UTF16 使用格式:UTF8toUTF16.exe <input> [output] 如果没有output,则覆盖源文件,否则输出到output中 方便命令行使用,批量转换文件编码
  • UTF8 UTF16 之间的互相转换

    千次阅读 2018-06-10 21:45:00
    首先需要知道 Unicode 编码范围 [U+00, U+10FFFF], 其中 [U+00, U+FFFF] 称为基础平面...0x010000 - 0x10FFFF 为辅助平面,共可存放16 * 65536个字符,划分为16个不同的平面 http://www.oschina.net/code/snipp...
    首先需要知道 Unicode 编码范围 [U+00, U+10FFFF], 其中 [U+00, U+FFFF] 称为基础平面(BMP), 这其中的字符最为常用.
    当然, 这 65536 个字符是远远不够的.
    0x010000 - 0x10FFFF 为辅助平面, 共可存放16 * 65536个字符,划分为16个不同的平面
     
    http://www.oschina.net/code/snippet_179574_15065
    按照如下的编码方式,对UTF8和UTF16之间进行转换 

    从UCS-2到UTF-8的编码方式如下(没有处理扩展面):

    UCS-2编码(16进制)UTF-8 字节流(二进制)
    0000 - 007F0xxxxxxx
    0080 - 07FF110xxxxx 10xxxxxx
    0800 - FFFF1110xxxx 10xxxxxx 10xxxxxx
     
    typedef unsigned long   UTF32;  /* at least 32 bits */
    typedef unsigned short  UTF16;  /* at least 16 bits */
    typedef unsigned char   UTF8;   /* typically 8 bits */
    typedef unsigned int    INT;
     
    /*
    UCS-2编码    UTF-8 字节流(二进制)
    0000 - 007F  0xxxxxxx
    0080 - 07FF 110xxxxx 10xxxxxx
    0800 - FFFF 1110xxxx 10xxxxxx 10xxxxxx
    */
     
    #define UTF8_ONE_START      (0xOOO1)
    #define UTF8_ONE_END        (0x007F)
    #define UTF8_TWO_START      (0x0080)
    #define UTF8_TWO_END        (0x07FF)
    #define UTF8_THREE_START    (0x0800)
    #define UTF8_THREE_END      (0xFFFF)
     
     
    void UTF16ToUTF8(UTF16* pUTF16Start, UTF16* pUTF16End, UTF8* pUTF8Start, UTF8* pUTF8End)
    {
        UTF16* pTempUTF16 = pUTF16Start;
        UTF8* pTempUTF8 = pUTF8Start;
     
        while (pTempUTF16 < pUTF16End)
        {
            if (*pTempUTF16 <= UTF8_ONE_END
                && pTempUTF8 + 1 < pUTF8End)
            {
                //0000 - 007F  0xxxxxxx
                *pTempUTF8++ = (UTF8)*pTempUTF16;
            }
            else if(*pTempUTF16 >= UTF8_TWO_START && *pTempUTF16 <= UTF8_TWO_END
                && pTempUTF8 + 2 < pUTF8End)
            {
                //0080 - 07FF 110xxxxx 10xxxxxx
                *pTempUTF8++ = (*pTempUTF16 >> 6) | 0xC0;
                *pTempUTF8++ = (*pTempUTF16 & 0x3F) | 0x80;
            }
            else if(*pTempUTF16 >= UTF8_THREE_START && *pTempUTF16 <= UTF8_THREE_END
                && pTempUTF8 + 3 < pUTF8End)
            {
                //0800 - FFFF 1110xxxx 10xxxxxx 10xxxxxx
                *pTempUTF8++ = (*pTempUTF16 >> 12) | 0xE0;
                *pTempUTF8++ = ((*pTempUTF16 >> 6) & 0x3F) | 0x80;
                *pTempUTF8++ = (*pTempUTF16 & 0x3F) | 0x80;
            }
            else
            {
                break;
            }
            pTempUTF16++;
        }
        *pTempUTF8 = 0;
    }
     
    void UTF8ToUTF16(UTF8* pUTF8Start, UTF8* pUTF8End, UTF16* pUTF16Start, UTF16* pUTF16End)
    {
        UTF16* pTempUTF16 = pUTF16Start;
        UTF8* pTempUTF8 = pUTF8Start;
     
        while (pTempUTF8 < pUTF8End && pTempUTF16+1 < pUTF16End)
        {
            if (*pTempUTF8 >= 0xE0 && *pTempUTF8 <= 0xEF)//是3个字节的格式
            {
                //0800 - FFFF 1110xxxx 10xxxxxx 10xxxxxx
                *pTempUTF16 |= ((*pTempUTF8++ & 0xEF) << 12);
                *pTempUTF16 |= ((*pTempUTF8++ & 0x3F) << 6);
                *pTempUTF16 |= (*pTempUTF8++ & 0x3F);
     
            }
            else if (*pTempUTF8 >= 0xC0 && *pTempUTF8 <= 0xDF)//是2个字节的格式
            {
                //0080 - 07FF 110xxxxx 10xxxxxx
                *pTempUTF16 |= ((*pTempUTF8++ & 0x1F) << 6);
                *pTempUTF16 |= (*pTempUTF8++ & 0x3F);
            }
            else if(*pTempUTF8 >= 0 && *pTempUTF8 <= 0x7F)//是1个字节的格式
            {
                //0000 - 007F  0xxxxxxx
                *pTempUTF16 = *pTempUTF8++;
            }
            else
            {
                break;
            }
            pTempUTF16++;
        }
        *pTempUTF16 = 0;
    }
     
     
    int main()
    {
        UTF16 utf16[256] = {L"你a好b吗234中国~!"};
        UTF8 utf8[256];
         
        UTF16ToUTF8(utf16, utf16+wcslen(utf16), utf8, utf8+256);
     
        memset(utf16, 0, sizeof(utf16));
     
        UTF8ToUTF16(utf8, utf8 + strlen(utf8), utf16, utf16+256);
     
     
        return 0;
    }
    

      UTF-16 并不比 UTF-8 更受待见, 只是 Windows 默认使用 UTF-16 而已, 所以不得不在它们之间做转换(如果你还在使用非 Unicode 编码, 那你已经是受到微软的毒害了)

      当然, 万恶的微软还是给出了更简单的方法的, 那就是下面的两个函数:

    WideCharToMultiByte

    将UTF-16(宽字符)字符串映射到新的字符串。新的字符串不一定来自多字节字符集。(那你取这个名字是闹哪样? 多字节字符集是什么鬼??? 你怎么不去屎)

    https://msdn.microsoft.com/en-us/library/windows/desktop/dd374130(v=vs.85).aspx

    MultiByteToWideChar 

    将字符串映射到UTF-16(宽字符)字符串。字符串不一定来自多字节字符集。

     https://msdn.microsoft.com/en-us/library/windows/desktop/dd319072(v=vs.85).aspx

     

    程序: 将 UTF-16 编码的字符串转换为 UTF-8 编码, 并在控制台输出

    #include <Windows.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void use(const char *utf8str) {
    	system("Pause");
    	system("chcp 65001");
    	if (utf8str == NULL) {
    		printf("NULL\n");
    		return;
    	}
    	printf("%s\n", utf8str);
    }
    
    char *utf16to8(const wchar_t *str) {
    	if (str == NULL) {
    		return NULL;
    	}
    	int cBuf = 0; // 缓冲区大小
    	// 计算缓冲区需要的大小, 如果函数成功, 则返回值至少是 2 (UTF-8以0x0000结尾)
    	if (cBuf = WideCharToMultiByte(
    		CP_UTF8,
    		0,
    		str,
    		-1,
    		NULL,
    		0,
    		NULL,
    		NULL), !cBuf ){
    			// 计算失败
    			fprintf(stderr, "计算内存失败!");
    			return NULL;
    	}
    	printf("缓冲区大小 %d .\n", cBuf);
    	char *buf = NULL; // 指向缓冲区
    	buf = (char *)malloc(cBuf); // 分配缓冲区
    	if (!WideCharToMultiByte(
    		CP_UTF8,
    		0,
    		str,
    		-1,
    		buf,
    		1024,
    		NULL,
    		NULL) ){
    			fprintf(stderr, "转换失败!\n");
    			return NULL;
    	}
    	// 返回缓冲区地址
    	return buf;
    }
    
    void run() {
    	const wchar_t *str = L"Hello你好我的朋友!";
    	char *utf8str = utf16to8(str);
    	use(utf8str);
         free(utf8str); } int main(int argc, char* argv[]) { run(); system("Pause"); return EXIT_SUCCESS; }

      Output如下------>

    缓冲区大小 25 .
    请按任意键继续. . .

    Active code page: 65001
    Hello你好我的朋友!
    Press any key to continue . . .

    上面这个函数调用了两次 WideCharToMultiByte(), 第一次是计算转换所需的空间, 第二次开始转换(It's stupid!)

    那么依葫芦画瓢, 你现在可以将 UTF-8 -> UTF16了吗?

     

     

    补两张图

     

     

     

     

    转载于:https://www.cnblogs.com/develon/p/9164566.html

    展开全文
  • utf-16编码表

    2018-06-01 19:29:17
    有61726个字符,csv格式,做编码的基础数据 0000, 0001,Ā 0002,Ȁ 0003,̀ 0004,Ѐ 0005,Ԁ 0006,؀ 0007,܀ 0008,ࠀ 0009,ऀ 000C,ఀ 000D,ഀ 000F,ༀ 0010,က 0011,ᄀ 0012,ሀ
  • 反转 UTF-16 字符串 优化的 UTF-16 兼容反向字符串算法。 它只需要遍历给定字符串的 1/2,并处理 UTF-16 代理对。... var reverse = require ( 'reverse-utf16-string' ) ; var reversed = reverse ( 'ab
  • UTF8与UTF16区别

    千次阅读 2017-12-06 09:17:16
    这样就出现了UTF-8,UTF16,UTF-32.原理和之前肯定是完全一样的,UTF-32就是把所有的字符都用32bit也就是4个字节来表示.然后UTF-8,UTF-16就视情况而定了.UTF-8可以选择1至8个字节中的任一个来表示.而UTF-16只能是选两字...
    

    为啥需要Unicode

     

          我们知道计算机其实挺笨的,它只认识0101这样的字符串,当然了我们看这样的01串时肯定会比较头晕的,所以很多时候为了描述简单都用十进制,十六进制,八进制表示.实际上都是等价的,没啥太多不一样.其他啥文字图片之类的其他东东计算机不认识.那为了在计算机上表示这些信息就必须转换成一些数字.你肯定不能想怎么转换就怎么转,必须得有定些规则.于是刚开始的时候就有ASCII字符集(American Standard Code for Information Interchange, "美国信息交换标准码),它使用7 bits来表示一个字符,总共表示128个字符,我们一般都是用字节(byte,即8个01串)来作为基本单位.那么怎么当用一个字节来表示字符时第一个bit总是0,剩下的七个字节就来表示实际内容.后来IBM公司在此基础上进行了扩展,用8bit来表示一个字符,总共可以表示256个字符.也就是当第一个bit是0时仍表示之前那些常用的字符.当为1时就表示其他补充的字符.

            英文字母再加一些其他标点字符之类的也不会超过256个.一个字节表示主足够了.但其他一些文字不止这么多 ,像汉字就上万个.于是又出现了其他各种字符集.这样不同的字符集交换数据时就有问题了.可能你用某个数字表示字符A,但另外的字符集又是用另外一个数字表示A.这样交互起来就麻烦了.于是就出现了Unicode和ISO这样的组织来统一制定一个标准,任何一个字符只对应一个确定的数字.ISO取的名字叫UCS(Universal Character Set),Unicode取的名字就叫unicode了.

          总结起来为啥需要Unicodey就是为了适应全球化的发展,便于不同语言之间的兼容交互,而ASCII不再能胜任此任务了.

     

    Unicode详细介绍

     

    1.容易产生后歧义的两字节

            unicode的第一个版本是用两个字节(16bit)来表示所有字符

            .实际上这么说容易让人产生歧义,我们总觉得两个字节就代表保存在计算机中时是两个字节.于是任何字符如果用unicode表示的话保存下来都占两个字节.其实这种说法是错误的.

         其实Unicode涉及到两个步骤,首先是定义一个规范,给所有的字符指定一个唯一对应的数字,这完全是数学问题,可以跟计算机没半毛钱关系.第二步才是怎么把字符对应的数字保存在计算机中,这才涉及到实际在计算机中占多少字节空间.

         所以我们也可以这样理解,Unicode是用0至65535之间的数字来表示所有字符.其中0至127这128个数字表示的字符仍然跟ASCII完全一样.65536是2的16次方.这是第一步.第二步就是怎么把0至65535这些数字转化成01串保存到计算机中.这肯定就有不同的保存方式了.于是出现了UTF(unicode transformation format),有UTF-8,UTF-16.

     

    2.UTF-8 与UTF-16的区别

        UTF-16比较好理解,就是任何字符对应的数字都用两个字节来保存.我们通常对Unicode的误解就是把Unicode与UTF-16等同了.但是很显然如果都是英文字母这做有点浪费.明明用一个字节能表示一个字符为啥整两个啊.

       于是又有个UTF-8,这里的8非常容易误导人,8不是指一个字节,难道一个字节表示一个字符?实际上不是.当用UTF-8时表示一个字符是可变的,有可能是用一个字节表示一个字符,也可能是两个,三个.当然最多不能超过3个字节了.反正是根据字符对应的数字大小来确定.

       于是UTF-8和UTF-16的优劣很容易就看出来了.如果全部英文或英文与其他文字混合,但英文占绝大部分,用UTF-8就比UTF-16节省了很多空间.而如果全部是中文这样类似的字符或者混合字符中中文占绝大多数.UTF-16就占优势了,可以节省很多空间.另外还有个容错问题,等会再讲

      看的有点晕了吧,举个例子.假如中文字"汉"对应的unicode是6C49(这是用十六进制表示,用十进制表示是27721为啥不用十进制表示呢?很明显用十六进制表示要短点.其实都是等价的没啥不一样.就跟你说60分钟和1小时一样.).你可能会问当用程序打开一个文件时我们怎么知道那是用的UTF-8还是UTF-16啊.自然会有点啥标志,在文件的开头几个字节就是标志.

    EF BB BF 表示UTF-8

    FE FF 表示UTF-16.

     

    用UTF-16表示"汉"

    假如用UTF-16表示的话就是01101100   01001001(共16 bit,两个字节).程序解析的时候知道是UTF-16就把两个字节当成一个单元来解析.这个很简单.

    用UTF-8表示"汉"

    用UTF-8就有复杂点.因为此时程序是把一个字节一个字节的来读取,然后再根据字节中开头的bit标志来识别是该把1个还是两个或三个字节做为一个单元来处理.

    0xxxxxxx,如果是这样的01串,也就是以0开头后面是啥就不用管了XX代表任意bit.就表示把一个字节做为一个单元.就跟ASCII完全一样.

    110xxxxx 10xxxxxx.如果是这样的格式,则把两个字节当一个单元

    1110xxxx 10xxxxxx 10xxxxxx 如果是这种格式则是三个字节当一个单元.

    这是约定的规则.你用UTF-8来表示时必须遵守这样的规则.我们知道UTF-16不需要用啥字符来做标志,所以两字节也就是2的16次能表示65536个字符.

    而UTF-8由于里面有额外的标志信息,所有一个字节只能表示2的7次方128个字符,两个字节只能表示2的11次方2048个字符.而三个字节能表示2的16次方,65536个字符.

    由于"汉"的编码27721大于2048了所有两个字节还不够,只能用三个字节来表示.

    所有要用1110xxxx 10xxxxxx 10xxxxxx这种格式.把27721对应的二进制从左到右填充XXX符号(实际上不一定从左到右,也可以从右到左,这是涉及到另外一个问题.等会说.

    刚说到填充方式可以不一样,于是就出现了Big-Endian,Little-Endian的术语.Big-Endian就是从左到右,Little-Endian是从右到左.

    由上面我们可以看出UTF-8需要判断每个字节中的开头标志信息,所以如果一当某个字节在传送过程中出错了,就会导致后面的字节也会解析出错.而UTF-16不会判断开头标志,即使错也只会错一个字符,所以容错能力强.

     

    Unicode版本2

        前面说的都是unicode的第一个版本.但65536显然不算太多的数字,用它来表示常用的字符是没一点问题.足够了,但如果加上很多特殊的就也不够了.于是从1996年开始又来了第二个版本.用四个字节表示所有字符.这样就出现了UTF-8,UTF16,UTF-32.原理和之前肯定是完全一样的,UTF-32就是把所有的字符都用32bit也就是4个字节来表示.然后UTF-8,UTF-16就视情况而定了.UTF-8可以选择1至8个字节中的任一个来表示.而UTF-16只能是选两字节或四字节..由于unicode版本2的原理完全是一样的,就不多说了.

    前面说了要知道具体是哪种编码方式,需要判断文本开头的标志,下面是所有编码对应的开头标志

    EF BB BF    UTF-8
    FE FF     UTF-16/UCS-2, little endian
    FF FE     UTF-16/UCS-2, big endian
    FF FE 00 00  UTF-32/UCS-4, little endian.
    00 00 FE FF  UTF-32/UCS-4, big-endian.

    其中的UCS就是前面说的ISO制定的标准,和Unicode是完全一样的,只不过名字不一样.ucs-2对应utf-16,ucs-4对应UTF-32.UTF-8是没有对应的UCS


    转自https://www.cnblogs.com/kingcat/archive/2012/10/16/2726334.html

    展开全文
  • 代码片段: ``` String s="hello你好"; String s1 = new String(s.getBytes("UTF-8"), "UTF-16");...问题来源:rpc请求 返回的是utf-16编码的字符串 用的时候需要转成utf-8 按照上面的代码 会出现乱码问题
  • Uteffer:使用C ++将UTF16转换为UTF8
  • utf8与utf16转换

    千次阅读 2019-03-14 23:18:59
    1.UTF8与UTF16编码转换 std::string ConvertFromUtf16ToUtf8(const std::wstring&amp; wstr) { std::string convertedString; int requiredSize = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, 0, 0, 0...
  • BOM(Byte Order Mark)在分析unicode之前,先把bom(byte order mark)说一下。...来举个很简单的例子,在windows下新建一个文本文件,并另存为utf8的文件格式: 该文件里面没有任何内容,我们再用Hex
  • UTF8、UTF16 之间的转换

    2015-11-26 12:38:44
    按照如下的编码方式,对UTF8和UTF16之间进行转换 从UCS-2到UTF-8的编码方式如下: UCS-2编码(16进制) UTF-8 字节流(二进制) 0000 - 007F 0xxxxxxx 0080 - 07FF 110xxxx
  • I need to convert that into a utf8 rune, so I can compare it to input I receive from the user, but I haven't found the right incantation of the hex/utf16/utf8 packages to do so. </div>
  • UTF-16汉字编码表

    2016-07-10 08:50:33
    UTF-16汉字编码表,txt格式的
  • JS下的GBK和UTF16编码转换

    千次阅读 2018-06-06 14:13:37
    JS中使用的是UTF-16编码,因为历史原因,中心端接收的数据是GBK编码的,因此需要进行转换操作。转换的原理是将GBK编码范围内的字符全部提取出来,并获取其对应的GBK编码和UTF-16编码,生成两张对照表。因为两者都是...
  • WINDOWS下UTF8/UTF16/ANSI相互转换

    千次阅读 2018-11-04 13:55:20
    目录编码知识代码演示 编码知识 字符编码发展简史(ASCII-EASCII-ANSI-UNICODE/UCS) ... * @param pWideBytes 宽字符(utf16编码)流指针 * @param cchChar 字符数,需要包含终止符数 * @param strR...
  • utf16编码格式也有4字节的情况

    千次阅读 2018-06-30 12:28:21
    转自:https://www.cnblogs.com/dragon2012/p/5020259.htmlUTF-16是Unicode...UTF-16编码规则如下:2.2.1 从U+D800到U+DFFF的码位(代理区)因为Unicode字符集的编码值范围为0-0x10FFFF,而大于等于0x10000的辅助...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 640,446
精华内容 256,178
关键字:

utf16