1. 程式人生 > >JavaScript編碼轉換(UTF-8、UTF-16)

JavaScript編碼轉換(UTF-8、UTF-16)

        JavaScript的字元用UTF16進行編碼,網頁常用的編碼是UTF8或者GB2312,在不涉及到字串位元組操作時,JavaScript編碼和網頁編碼即使不一致也可以使用。但是當進行諸如Base64涉及位元組之類的操作,尤其是有中文字元時,JavaScript編碼的字元內容在網頁中或者在伺服器端顯示為亂碼。因此在進行位元組操作時必須把JavaScript編碼轉成網頁編碼。在進行編碼轉換之前,先普及計算機字元編碼及實現。

字元編碼基礎

        計算機最開始只支援ASCII碼,一個字元用一個位元組表示,只用了低7位,最高位為0,因此總共有128個ASCII碼,範圍為0~127。後來為了支援多種地區的語言,各大組織機構和IT廠商開始發明它們自己的編碼方案,以便彌補ASCII編碼的不足,如GB2312編碼、GBK編碼和Big5編碼等。但這些編碼都只是針對區域性地區或少數語言文字,沒有辦法表達所有的語言文字。而且這些不同的編碼之間並沒有任何聯絡,它們之間的轉換需要通過查表來實現。為了提高計算機的資訊處理和交換功能,使得世界各國的文字都能在計算機中處理,從1984年起,ISO組織就開始研究制定一個全新的標準:通用多八位(即多位元組)編碼字符集(Universal Multiple-Octet Coded Character Set),簡稱UCS。標準的編號為:ISO 10646。這一標準為世界各種主要語言的字元(包括簡體及繁體的中文字)及附加符號,編制統一的內碼。統一碼(Unicode)是Universal Code的縮寫,是由另一個叫“Unicode學術學會”(The Unicode Consortium)的機構制定的字元編碼系統。Unicode與ISO 10646國際編碼標準從內容上來說是同步一致的。

ANSI

    ANSI不代表具體的編碼,它是指本地編碼。比如在簡體版windows上它表示GB2312編碼,在繁體版windows上它表示Big5編碼,在日文作業系統上它表示JIS編碼。所以如果新建了個文字檔案並儲存為ANSI編碼,那麼這個檔案的編碼為本地編碼。

Unicode

    Unicode編碼方式與ISO 10646的通用字符集概念相對應。目前實際應用的Unicode版本對應於UCS-2,使用16位編碼空間,也就是每個字元佔用2個位元組。這樣理論上一共最多可以表示2的16次方(即65536)個字元,基本滿足各種語言的使用。實際上當前版本的Unicode並未完全使用這16位編碼,而是保留了大量空間以作為特殊使用或將來擴充套件。

    Unicode編碼是和字元表一一對映的。比如4EBA代表漢字'人',這種對映關係是固定不變的。通俗的說Unicode編碼就是字元表的座標,通過4EBA就能找到漢字'人'。

    Unicode的實現方式不同於編碼方式。一個字元的Unicode編碼是確定的,但是由於不同系統平臺的設計不一致,以及出於節省空間考慮,Unicode編碼的實現方式有所不同。Unicode的實現方式稱為Unicode轉換格式(Unicode Transformation Format,簡稱為UTF)。UTF8、UTF16、GB2312都是Unicode編碼的實現。

UTF-16

    UTF-16把Unicode字符集的抽象碼位對映為16位長的整數序列,即用固定2位元組儲存Unicode編碼。UTF-16編碼是Unicode最直接的實現方式,通常我們在windows上新建文字檔案後儲存為Unicode編碼,其實就是儲存為UTF-16編碼。因為是多位元組儲存,所以UTF-16儲存方式分為2種:大端序和小端序。漢字人的Unicode編碼是4EBA,以大端序儲存為4E BA,以小端序儲存為BA 4E,Windows和Linux使用小端序儲存方式。

UTF-8

    UTF-8(8-bit Unicode Transformation Format)是一種針對Unicode的可變長度字元編碼,為1~6個位元組。UTF-8的編碼規則:

1、128個US-ASCII字元只需一個位元組編碼(Unicode範圍由U+0000至U+007F)。

2、帶有附加符號的拉丁文、希臘文、西裡爾字母、亞美尼亞語、希伯來文、阿拉伯文、敘利亞文及它拿字母則需要兩個位元組編碼(Unicode範圍由U+0080至U+07FF)。

3、其他基本多文種平面(BMP)中的字元(這包含了大部分常用字)使用三個位元組編碼(Unicode範圍由U+0800至U+FFFF)。

4、其他極少使用的Unicode 輔助平面的字元使用四至六位元組編碼(Unicode範圍由U+10000至U+1FFFFF使用四位元組,Unicode範圍由U+200000至U+3FFFFFF使用五位元組,Unicode範圍由U+4000000至U+7FFFFFFF使用六位元組)。

GB2312

    GB2312是中華人民共和國國家標準簡體中文字符集,通行於中國大陸,新加坡等地也採用此編碼,中國大陸幾乎所有的中文系統和國際化的軟體都支援GB2312。GB2312中對所收漢字進行了分割槽處理,每區含有94個漢字/符號,這種表示方式也稱為區位碼。

01-09區為特殊符號。

16-55區為一級漢字,按拼音排序。

56-87區為二級漢字,按部首/筆畫排序。

10-15區及88-94區則未有編碼。

    舉例來說,啊是GB2312之中的第一個漢字,它的區位碼就是1601。
    GB2312通常採用EUC儲存方法,以便兼容於ASCII。ASCII字元用單位元組表示,漢字及符號以兩個位元組表示。第一個位元組稱為高位位元組(也稱區位元組),第二個位元組稱為低位位元組(也稱位位元組)。高位位元組使用了0xA1-0xF7(把01-87區的區號加上0xA0),低位位元組使用了0xA1-0xFE(把01-94加上 0xA0)。由於一級漢字從16區起始,漢字區的高位位元組的範圍是0xB0-0xF7,低位位元組的範圍是0xA1-0xFE,佔用的碼位是72*94=6768。其中有5個空位是D7FA-D7FE。例如啊字在大多數程式中,會以兩個位元組0xB0(第一個位元組)0xA1(第二個位元組)儲存。區位碼=區位元組+位位元組(與區位碼對比:0xB0=0xA0+16,0xA1=0xA0+1)。

UTF-16和UTF-8轉換

UCS-2編碼(UTF-16) UTF-8二進位制位元組流
0000 - 007F 0xxxxxxx
0080 - 07FF 110xxxxx  10xxxxxx
0800 - FFFF 1110xxxx  10xxxxxx  10xxxxxx

//UTF-16轉UTF-8
function utf16ToUtf8(s){
	if(!s){
		return;
	}
	
	var i, code, ret = [], len = s.length;
	for(i = 0; i < len; i++){
		code = s.charCodeAt(i);
		if(code > 0x0 && code <= 0x7f){
			//單位元組
			//UTF-16 0000 - 007F
			//UTF-8  0xxxxxxx
			ret.push(s.charAt(i));
		}else if(code >= 0x80 && code <= 0x7ff){
			//雙位元組
			//UTF-16 0080 - 07FF
			//UTF-8  110xxxxx 10xxxxxx
			ret.push(
				//110xxxxx
				String.fromCharCode(0xc0 | ((code >> 6) & 0x1f)),
				//10xxxxxx
				String.fromCharCode(0x80 | (code & 0x3f))
			);
		}else if(code >= 0x800 && code <= 0xffff){
			//三位元組
			//UTF-16 0800 - FFFF
			//UTF-8  1110xxxx 10xxxxxx 10xxxxxx
			ret.push(
				//1110xxxx
				String.fromCharCode(0xe0 | ((code >> 12) & 0xf)),
				//10xxxxxx
				String.fromCharCode(0x80 | ((code >> 6) & 0x3f)),
				//10xxxxxx
				String.fromCharCode(0x80 | (code & 0x3f))
			);
		}
	}
	
	return ret.join('');
}
//UTF-8轉UTF-16
function utf8ToUtf16(s){
	if(!s){
		return;
	}
	
	var i, codes, bytes, ret = [], len = s.length;
	for(i = 0; i < len; i++){
		codes = [];
		codes.push(s.charCodeAt(i));
		if(((codes[0] >> 7) & 0xff) == 0x0){
			//單位元組  0xxxxxxx
			ret.push(s.charAt(i));
		}else if(((codes[0] >> 5) & 0xff) == 0x6){
			//雙位元組  110xxxxx 10xxxxxx
			codes.push(s.charCodeAt(++i));
			bytes = [];
			bytes.push(codes[0] & 0x1f);
			bytes.push(codes[1] & 0x3f);
			ret.push(String.fromCharCode((bytes[0] << 6) | bytes[1]));
		}else if(((codes[0] >> 4) & 0xff) == 0xe){
			//三位元組  1110xxxx 10xxxxxx 10xxxxxx
			codes.push(s.charCodeAt(++i));
			codes.push(s.charCodeAt(++i));
			bytes = [];
			bytes.push((codes[0] << 4) | ((codes[1] >> 2) & 0xf));
			bytes.push(((codes[1] & 0x3) << 6) | (codes[2] & 0x3f));			
			ret.push(String.fromCharCode((bytes[0] << 8) | bytes[1]));
		}
	}
	return ret.join('');
}


相關推薦

JavaScript編碼轉換UTF-8UTF-16

        JavaScript的字元用UTF16進行編碼,網頁常用的編碼是UTF8或者GB2312,在不涉及到字串位元組操作時,JavaScript編碼和網頁編碼即使不一致也可以使用。但是當進行諸如Base64涉及位元組之類的操作,尤其是有中文字元時,JavaScri

弄懂進位制bitjava基本資料型別byteshortint char StringASCIIUnicodeUTF-8UTF-16的關聯關係及UTF-8UTF-16編碼原理

首先普及一下基本概念: 1.數值(百度百科):指的是用數目表示的一個量的多少; 2.進位制(百度百科):也就是進位計數制,是人為定義的帶進位的計數方法。對於任何一種進位制---X進位制,就表示每一位置上的數運算時都是逢X進一位。 十進位制是逢十進一,十六進位制是逢十六進一,二進位制就是逢二進

Java_字元編碼UnicodeUTF-8UTF-16

首先看一下下面的程式(測試英文和中文在Unicode、UTF-8、UTF-16這三種編碼下,一個字元佔幾個位元組) System.out.println("a(Unicode) :" + "a".getBytes("Unicode").length)

UTF-8UTF-16UTF-32編碼的相互轉換

相關文章 最近在考慮寫一個可以跨平臺的通用字串類,首先需要搞定的就是編碼轉換問題。 vs預設儲存程式碼檔案,使用的是本地code(中文即GBK,日文即Shift-JIS),也可以使用帶BOM的UTF-8。 gcc則是UTF-8,有無BOM

ASCIIGB2312GBKUnicodeUTF-8UTF-16 編碼方式比較分析

實際上在日常工作開發中,中文亂碼是經常出現的一類問題。下面介紹一下ASCII、GB2312、GBK、Unicode、UTF-8、UTF-16、UTF-32編碼的原理以及不同點和區別。 ASCII ASCII的英文翻譯是:American Standard Code f

常見的字元編碼UTF-8UTF-16UTF-32

字符集 字符集為每個字元分配了一個唯一的編號,通過這個編號就能找到對應的字元。在程式設計過程中我們經常會使用字元,而使用字元的前提就是把字元放入記憶體中,毫無疑問,放入記憶體中的僅僅是字元的編號,而不是真正的字元實體。 如何才能將字元編號放入記憶體中呢? 對於

Java中的UTF-8UTF-16編碼字元所佔位元組數

前言:上一篇文章寫了關於Unicode,以及utf-8、utf-16相關知識。所以本篇博文來驗證在java環境下,字元在不同編碼下所佔的字計數。 測試程式碼如下: package string; public class CharByteTes

ASCIIUnicodeUTF-8UTF-8without BOMUTF-16UTF-32傻傻分不清

文件 修改編碼 常用 文件的 ans with 使用 常見 中文 目錄 ASCII、Unicode、UTF-8、UTF-8(without BOM)、UTF-16、UTF-32傻傻分不清 前言

Java基礎語法-UnicodeUTF-8UTF-16

1.Unicode(統一碼、萬國碼),從名字裡可以看出,unicode碼錶囊括世界上各國語言文字。 unidode中包含17個程式碼級別,第一個程式碼級別又稱作基本的多語言級別(碼點從U+0000到U+FFFF),其餘16個程式碼級別(碼點從U+10000到U+10FFFF)包含一些輔助字元。這裡說

UCS-2UCS-4UTF-8UTF-16UTF-32介紹

轉載地址:https://charlee.li/unicode-intro.html 基本知識    (1) 位元組和字元的區別        咦,位元組和字元能有什麼區別啊?不都是一樣的嗎?完全正確,但只是在古老的DOS時代。

理解unicodeascii和utf-8utf-16

1.ASCII        標準ASCII碼字符集總共的編碼有128個,包括32個通用控制符,10個十進位制數碼,52個英文大小寫字母和34個專用符號。這是為了方便,規定ASCII碼為正,即後7位可用,共2^7=128。        為了納入更多的字元,用上第一位的符

淺析unicode和UTF-8UTF-16UTF-32的區別

1、區別編碼字符集和字符集編碼 首先要注意的是unicode是編碼字符集,而UTF-8、UTF-16、UTF-32是字符集編碼(好繞哎有沒有)。下面我來具體解釋一下: 比如漢字的”漢”,在unicode中,漢”的unicode值為0x6C49。問:把這個”漢

UTF-8UTF-16Unicode的區別

        看了很多網上的總結,我撈出來最乾的部分羅列在這裡,希望對大家有幫助          字符集是指字元的集合,例如所有的英文字母是字符集,所有的漢字也是字符集,全世界所有語言的符號都放在一起,也可以稱為一個字符集,字符集中的字元沒有順序之分,在給字元集合中的每

unicode與gbk雙向編碼轉換分離底層,便於移植

unicode與gbk雙向編碼轉換表在簡訊解析,FATFS長檔名等都有用到,我一般是將編碼表放置於外部falsh,與字型檔放到一起,本次將編碼表的底層進行了分離,並且對編碼表進行檢測,具體實現如下:底層儲存器介面分離後,可以將編碼表存放於記憶體,內部flash,外部flash

JAVA語言程式設計 第十七章 17.817.9

程式小白,希望和大家多交流,共同學習 17.8_1 import java.io.File; import java.io.PrintWriter; import java.util.Scanner; import java.io.IOExceptio

C++中字符編碼轉換(UnicodeUTF-8ANSI)

編碼規則 相關 window size_t 簡體 意思 cas 百度百科 了解 C++的項目,字符編碼是一個大坑,不同平臺之間的編碼往往不一樣,如果不同編碼格式用一套字符讀取格式讀取就會出現亂碼。因此,一般都是轉化成UTF-8這種平臺通用,且支持性很好的編碼格式。 Uni

常見的幾種編碼(ANSIGBKGB2312UTF-8GB18030和 UNICODE)介紹

比特流 這一 數學 str odin 似的 英語 信息 繼續 轉載:http://blog.jobbole.com/30526/ 編碼一直是讓新手頭疼的問題,特別是 GBK、GB2312、UTF-8 這三個比較常見的網頁編碼的區別,更是讓許多新手暈頭轉向,怎麽解釋也解釋不清

編碼(ACSII unicod UTF-8)QT輸出中文亂碼深入分析

們的 解決方法 ces size 虛擬 類型 col 機器 編碼規則 總結: 1. qt輸出中文亂碼原因分析 qt的編程環境默認是utf-8編碼格式(關於編碼見下文知識要點一); cout << "中文" << endl; 程序運行,程序並不認識

轉 MFC中 GB2312UTF-8unicode 之間轉換

//GB2312到UTF-8的轉換static int GB2312ToUtf8(const char* gb2312, char* utf8){int len = MultiByteToWideChar(CP_ACP, 0, gb2312, -1, NULL, 0);wchar_t* wstr = new

unicodeutf-8ansigbkgb2312編碼詳解

前言 作為一個開發人員或是測試人員,免不了要與各種各樣的編碼打交道,而且這些各種編碼總是讓人頭大,現在我們就來揭開他們的廬山真面目 移動還是聯通? 在開始本文前,我需要大家思考一個問題:你知道聯通為什麼幹不過移動嗎? 我們來看看微軟站在哪邊吧,用記事本寫下聯通