位(bit)、字節(byte)、字符、編碼之間的關系


位(bit)、字節(byte)、字符、編碼之間的關系

一. 位(bit)

  • 是數據存儲的最小單位
  • 又稱比特位,英文是bit。表示的意義是一個位,也就是1或者0。

二.字節(byte)

  • 又稱8位二進制,英文是byte。表示的意義是八個位,也就是01010101

  • 1 KB = 1024 B(字節);
    

    ​ 1 MB = 1024 KB; (2^10 B)

    ​ 1 GB = 1024 MB; (2^20 B)

    ​ 1 TB = 1024 GB; (2^30 B)

三.字符

 a、A、中、+、*、の......均表示一個字符;

 一般 utf-8 編碼下,一個漢字字符占用3個字節;

 一般 gbk 編碼下,一個漢字字符占用2個字節;

四.字符集

 即各種各個字符的集合,也就是說哪些漢字,字母(A、b、c)和符號(空格、引號..)會被收入標准中;

五.編碼

 	規定每個“字符”分別用一個字節還是多個字節存儲,用哪些字節來存儲,這個規定就叫做“編碼”。(其實際是對字符集中字符進行編碼,即:每個字符用二進制在計算中表示存儲);
 	通俗的說:編碼就是按照規則對字符進行翻譯成對應的二進制數,在計算器中運行存儲,用戶看的時候(比如瀏覽器),在用對應的編碼解析出來用戶能看懂的;
(1)標准ASCii字符集:有96個打印字符,和32個控制字符組成;一共96+32=128個;
         用7位二進制數來對每1個字符進行編碼;
         而由於7位還還不夠1個字節,而電腦的內部常用字節來用處理,每個字節中多出來的最高位用0替代;

         0 000   0000.........................0

         0 111    1111..........................127;   從0----127,來表示128個ACSii編碼;

     比如:字符 'A'----------在計算器內部用0100 0001 (65)來表示;
          字符'a'-----------在計算器內部用0 110 0001 (97)來表示;

     注意:'10'在計算器內部是沒有編碼的,因為它是字符串,而不是單個字符。可以分別對1,0字符編碼存儲;
	(2)擴展ASCii字符集:將標准的ASCii最高位1,得到十進制代碼128---255(1 000 0000----1 111 1111);所以字符集一共有0---255,  256個字符;
	(3)gb2312字符集: 所有漢字字符在計算機內部采用2個字節來表示,每個字節的最高位規定為1【正好與標准ASCii字符(最高位是0)不重疊,並兼容】,不支持繁體字;所以:gb2312表示漢字的編碼為:[129--255][129--255]  (兩個字節,每個字節最高位是1);小於127的字符,與ASCii編碼相同;

	(4)gbk字符集:gb2312的擴充,兼容gb2312,除了收錄gb2312所有的字符外,還收錄了其他不常見的漢字、繁體字等;
	gbk中字符是一個或兩個字節,單字節字符00--7F(0---127)這個區間和ASCII是一樣的;
	雙字節字符的第一個字節是在81--FE(129--254)之間。通過這個可以判斷是單字節還是雙字節;即:在gbk字符編碼,如果第一個字節是>128的,則再往后找一個字節,組成漢字;如果第一個字節<128,則表示的是一個單字節(此時和ASCII是一樣的);
<?php
// gbk編碼下,無亂碼截取中文字符;

// 方法1:自定義函數1;

function subgbk($str,$lens){  // 形參 $str 表示將要截取的原始字符串, $lens 表示 設定需要截取的 字符 個數;
if($lens<=0){
	
	return '';
}

$chars = 0;   // 計算,統計已經截取的字符個數;
$res = '';    //  已經截取的字符長度;
$offset = 0;  // 偏移量,從字符串中那個字節開始截取;

$lengths = strlen($str);    // 將要截取的原始字符串 字節 的數;
while($chars<$lens && $offset<$lengths){
	
	$hight = ord(substr($str,$offset,1));  // 計算出 gbk字符中 高字節的所對應編碼的值;
	if($hight>128){		
// 截取兩個字節,代表一個字符;即:雙字節字符;
		$count = 2;
	}else{
		
		//截取一個字節,代表一個字符,即:單字節字符;
		$count = 1;
	}
	
	$res .= substr($str,$offset,$count);
	$offset += $count;
	$chars++;
}	

return $res;
}
?>

<?php
// 方法2:自定義函數2;

// 思路:先把字符串中 所有的 字符 逐一取出來  組成數組,然后對 數組元素 進行截取;最后截取出的數組拼接成想要的字符串;

function strgbk2($str,$strat,$length=NULL){   // 第三個參數默認設置的值是NULL,這個參數是參考了下邊的array_slice()函數,如果省略的話,則表示,一直截取到最后末尾;
	
$zijielen = strlen($str);    //  計算出 原始字符串 $str 的 字節長度;

$chars = 0;     // 統計計算截取的 字符 數;

$zifuarr = array();  //將字符串按照 字符 的形式 分割到 數組中;(待存儲);	

for($i = 0;$i<$zijielen;){  // $i 表示 原始字符串 $str 中的字節(標記); 
	
	if(ord(substr($str,$i,1)) > 128){
		// 雙字節字符,兩個字節來表示一個字符;
		
		$zifuarr[] = $str[$i].$str[$i+1];
	//	$zifuarr[] = substr($str,$i,2);    兩種寫法的意思是一樣的,都是 取得 某個字符 某些的 字節;
		$i += 2;
	}else{
		//  單字節字符,一個字節表示一個字符;
		
		$zifuarr[] = $str[$i];
	//	$zifuarr[] = substr($str,$i,1);	兩種寫法的意思是一樣的,都是 取得 某個字符 某個的 字節;
		$i++;
	}
	
   $chars++;        // 每次循環,相當於截取一個存儲 字符;  相當於所有的數組元素個數 count($zifuarr);
}
	
if($chars < $strat){    //  當偏移 過 字符 總長度時候;(開始截取的位置,已經超過了字符的總長度);
	return 'No characters have been found !';
}

return implode(array_slice($zifuarr,$strat,$length));  // array_slice()是截取數組一部分;implode()是將截取出來的字符串,鏈接起來;
  }

?>

<?php  
 // 方法3:用php內置的函數 mb_substr截取;

//此函數和 mb_strlen()函數一樣,都是針對 多字節 字符 的操作函數,在特定的編碼下,針對 字符 的 截取(mb_substr)和長度的計算(mb_strlen);

$strgbk = 'ds我是fdg一個中國xghdt人';
echo mb_substr($strgbk,2,3,'gbk');  // 我是f

?>   

(5)Unicode字符集:容納世界上所有語言字符和符號的集合;(以及對應的二進制數字);Unicode只是一個編碼規范,目前實際實現的unicode編碼只要有三種:UTF-8,UCS-2和UTF-16,三種unicode字符集之間可以按照規范進行轉換

(6)utf-8編碼:UTF-8(8-bit Unicode Transformation Format)是一種針對Unicode的可變長度字符編碼,也是一種前綴碼。它可以用來表示Unicode標准中的任何字符,且其編碼中的第一個字節仍與ASCII兼容,這使得原來處理ASCII字符的軟件無須或只須做少部分修改,即可繼續使用。因此,它逐漸成為電子郵件、網頁及其他存儲或發送文字的應用中,優先采用的編碼。

對於UTF-8編碼中的任意字節B,如果B的第一位為0,則B獨立的表示一個字符(ASCII碼);

如果B的第一位為1,第二位為0,則B為一個多字節字符中的一個字節(非ASCII字符);

如果B的前兩位為1,第三位為0,則B為兩個字節表示的字符中的第一個字節;

如果B的前三位為1,第四位為0,則B為三個字節表示的字符中的第一個字節;

如果B的前四位為1,第五位為0,則B為四個字節表示的字符中的第一個字節;

因此,對UTF-8編碼中的任意字節,根據第一位,可判斷是否為ASCII字符;根據前二位,可判斷該字節是否為一個字符編碼的第一個字節;根據前四位(如果前兩位均為1),可確定該字節為字符編碼的第一個字節,並且可判斷對應的字符由幾個字節表示;根據前五位(如果前四位為1),可判斷編碼是否有錯誤或數據傳輸過程中是否有錯誤。

即:
1、單字節的字符,字節的第一位設為0,對於英語文本,UTF-8碼只占用一個字節,和ASCII碼完全相同;
2、n個字節的字符(n>1),第一字節的前n位設為1,第n+1位設為0,后面字節的前兩位都設為10;

​ 3、2個字節,第一個字節的前2位是1;3個字節,第一個字節的前三位是1; 4個字節,第一個字節的前4位都是1;

// 如何截取中文,無亂碼,假設utf-8編碼;
<?php
// 方法1:自定義函數;
function subutf8($str,$len){  // 兩個形式參數,$str代表原始目標字符串,$len表示需要截取 字符 的個數;   注意是 字符的 個數;
if($len<=0){     // 當 將要截取的字符數 <=0的時候 返回 空字符串;
		return '';
	}
			
​		$chars = 0 ;                                // $chars 參數 代表 已經截取的字符的個數, 默認初始設置為0;
​		$res = '';                                  // $res 參數 表示  已經截取的字符串的長度, 默認初始設置為空(字符串);
​		$offset = 0;                                // $offset 參數 表示 字節 截取的偏移量; 即從字符串中(偏移幾個字節)哪個字節開始截取; 
​		$lengths = strlen($str);                    // $lengths 參數 表示 原始整個字符串的 字節的長度;   而應保證 $offset < $lengths; 否則都無字符可截取; 
		
		while($chars<$len && $offset < $lengths){   // $chars<$len; 應是<  而不是<= ;因為是從0開始的,並執行循環截取的;
				$higher = decbin(ord(substr($str,$offset,1)));  // 計算出 一個字符 中 第一個字節(高字節)的二進制;
		
		if(strlen($higher) < 8){      // decbin()函數 轉換出來的 二進制數 如果 <128(10000000) 的時候,即是二進制長度<8位的時候,前面高位不默認補0;
			// 截取一個字節;(表示一個字符);
			$count = 1;
			
		}else if(substr($higher,0,3) == '110'){
			//截取兩個字節(表示一個字符);
			$count = 2;
			
		}else if(substr($higher,0,4) == '1110'){
			//截取三個字節(表示一個字符);
			$count = 3;
			
		}else if(substr($higher,0,5) == '11110'){
			//截取四個字節(表示一個字符);
			$count = 4;
			
		}else if(substr($higher,0,6) == '111110'){
			//截取五個字節(表示一個字符);
			$count = 5;
			
		}else if(substr($higher,0,7) == '1111110'){
			//截取六個字節(表示一個字符);
			$count = 6;
			
		}
		
		$res .= substr($str,$offset,$count);
		
		$offset += $count;
		
		$chars++;
		
	}

return $res;
}

?>

<?php
//方法2:使用系統函數截取
mb_substr(),不會亂碼.例:
$str = '換s幾ss個字實現中文字串截取無亂碼的方法。';
echo mb_substr($str,0,5,'UTF-8');// '換s幾ss'

?>php
// 中文字符串實現反轉;

$a = '我是一個好人';
function strrevv($str) {
	$strlen = mb_strlen($str,'UTF-8');
	$arr = array();
	for($a=0;$a<=$strlen;$a++) {
		
$arr[] = mb_substr($str,$a,1,'UTF-8');
}

$newstr = implode('',array_reverse($arr));
return $newstr;
    }
echo strrevv($a);

// mb_strlen(str,utf-8);   字符串中字符的個數;

// mb_substr(str,start,length,utf-8); 多字節字符的截取;

// mb_strpos(str,needle,offset,utf-8);查找子字符串,在字符串中出現的位置;

// mb_substr_count(str,needle,utf-8);統計子字符串,在字

作者:羅文祥
來源:祥SHAO
原文:https://www.cnblogs.com/LWX-YEER/p/11203185.html
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM