成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

文件和字符編碼

_Zhao / 2822人閱讀

摘要:為了消除文件格式和字符編碼的疑惑,上網(wǎng)搜索并翻出以前收藏的文章,心結(jié)總算了卻。本文即是對(duì)文件和字符編碼的個(gè)人總結(jié)。雙字節(jié)多字節(jié)字符,編碼方式和字節(jié)序,才是困擾程序員的問(wèn)題。使用兩個(gè)字節(jié)表示一個(gè)字符,平臺(tái)默認(rèn)的字符編碼方案都是。

轉(zhuǎn)載請(qǐng)注明來(lái)源:https://tlanyan.me/ascii-bina...

近期對(duì)識(shí)別文件格式感到好奇,不幸和字符編碼搞混,不明其中原理導(dǎo)致心煩意亂。為了消除文件格式和字符編碼的疑惑,上網(wǎng)搜索并翻出以前收藏的文章,心結(jié)總算了卻。本文即是對(duì)文件和字符編碼的個(gè)人總結(jié)。

文本文件和二進(jìn)制

剛開(kāi)始的疑惑是:文本文件和二進(jìn)制文件有什么區(qū)別?為什么一個(gè)能顯示內(nèi)容,另一個(gè)的內(nèi)容經(jīng)常無(wú)法(用文本編輯器)正常顯示?

馬里蘭大學(xué)的這篇培訓(xùn)筆記,把兩者的區(qū)別講得清楚:文本文件是二進(jìn)制文件的一種,底層存儲(chǔ)也是0和1;文本文件可讀性和移植性好,但表現(xiàn)字符有限;二進(jìn)制文件數(shù)據(jù)存儲(chǔ)緊湊,無(wú)字符編碼限制。文本文件基本上只能存放數(shù)字、文字、標(biāo)點(diǎn)等有限字符組成的內(nèi)容;二進(jìn)制沒(méi)有字符約束,可隨意存儲(chǔ)圖像、音視頻等數(shù)據(jù)。

用存儲(chǔ)數(shù)字的例子可以形象的看出文本文件和二進(jìn)制文件存儲(chǔ)內(nèi)容上的差異。例如要存儲(chǔ)數(shù)字1234567890,文本文件要存儲(chǔ)0-9這十個(gè)數(shù)字的ASCII碼,對(duì)應(yīng)的十六進(jìn)制表示為:31 32 33 34 35 36 37 38 39 30,占用10個(gè)字節(jié);1234567890對(duì)應(yīng)的二進(jìn)制為“?0100 1001 1001 0110 0000 0010 1101 0010?”,占用4個(gè)字節(jié)(二進(jìn)制表示32位,一個(gè)字節(jié)8位),存儲(chǔ)到文件的16進(jìn)制表示為(大端):49 96 02 D2。

文本文件按字符存放內(nèi)容,二進(jìn)制按字節(jié)存放,這是兩種文件最本質(zhì)的區(qū)別。根據(jù)這個(gè)特性,可以推斷出一些常見(jiàn)結(jié)論:二進(jìn)制文件常常比文本文件緊湊,占用空間少;文本文件更友好易用,能用所見(jiàn)即所得的方式編輯;二進(jìn)制文件常常需要專用程序打開(kāi),等等。

回過(guò)頭看文本編輯器打開(kāi)二進(jìn)制文件常常是亂碼的現(xiàn)象。例如一個(gè)二進(jìn)制文件存放了一個(gè)整數(shù)1234(四個(gè)字節(jié)),用16進(jìn)制表示為:00 00 04 D2。文本編輯器打開(kāi)后逐個(gè)字符解釋,會(huì)發(fā)現(xiàn)這幾個(gè)字節(jié)拼不出可顯示的字符,只好亂碼相待。亂碼的原因是文本編輯器不能正確解析字節(jié)流,這也是二進(jìn)制文件需要用專用軟件打開(kāi)的原因。例如jpg文件要用看圖軟件打開(kāi),如果用音樂(lè)播放器打開(kāi),完蛋!視頻文件要用播放器打開(kāi),用壓縮軟件打開(kāi),歇菜!

文件格式

了解文本文件和二進(jìn)制文件的區(qū)別后,再來(lái)看文件格式。我們知道,Windows按文件拓展名識(shí)別文件格式,并調(diào)用對(duì)應(yīng)的程序打開(kāi)文件;(類)Unix系統(tǒng),拓展名可有可無(wú),那么怎么知道這個(gè)文件是什么格式呢?

幸好有file命令,這個(gè)命令可以告訴我們文件到底是什么格式。文件拓展名不是文件格式的本質(zhì)區(qū)別,內(nèi)容才是。把a(bǔ).zip改成a.txt/a.jgp/a.mp3,無(wú)論什么文件名,file都讓其原形畢露:Zip archive data, at least v1.0 to extract

file命令的工作原理可這篇文章。

編碼

說(shuō)完了文件,再來(lái)說(shuō)文件內(nèi)容中的編碼。常見(jiàn)的127個(gè)ASCII字符,沒(méi)啥編碼好說(shuō)的,反正幾乎所有的編碼方式都兼容它。雙字節(jié)、多字節(jié)字符,編碼方式和字節(jié)序,才是困擾程序員的問(wèn)題。一個(gè)漢字,GBK編碼需要兩個(gè)字節(jié),還要考慮本機(jī)的大小端,才能確定存放的最終形式;網(wǎng)絡(luò)通訊時(shí),要轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)序(大端序),接收方才能正常解析。開(kāi)發(fā)人員如果對(duì)字符編碼不熟悉,通信時(shí)遇到亂碼問(wèn)題,調(diào)試就很困難。

UCS(Universal Multiple Octet Coded Character Set)標(biāo)準(zhǔn)的制定,讓開(kāi)發(fā)人員遠(yuǎn)離混亂的多字節(jié)字符集。UCS標(biāo)準(zhǔn)里,所有的字符都有唯一的碼點(diǎn)(Code Point),根據(jù)碼點(diǎn)就可查到對(duì)應(yīng)字符。UCS用兩個(gè)字節(jié)表示一個(gè)碼點(diǎn)(UCS-4標(biāo)準(zhǔn)是4個(gè)字節(jié)),對(duì)應(yīng)一個(gè)字符。由于使用了兩個(gè)字節(jié),可容納2^16-1(6w+)字符,基本上容下各國(guó)常用的字符(UCS-4理論上可容納上二十億個(gè)字符,目前收納超過(guò)16W個(gè)字符)。注意UCS只是一個(gè)標(biāo)準(zhǔn),規(guī)定了碼點(diǎn)與字符的一一對(duì)應(yīng)關(guān)系,但沒(méi)有定義如何存儲(chǔ)在計(jì)算機(jī)中。

規(guī)定Unicode字符存儲(chǔ)方式的工作由UTF(Unicode Transformation Format)完成,應(yīng)用最多的方案是UTF-16和UTF-8。UTF-16使用兩個(gè)字節(jié)表示一個(gè)字符,Windows, MacOS, Java平臺(tái)默認(rèn)的字符編碼方案都是UTF-16。由于有兩個(gè)字節(jié),便存在大端和小端兩種方案的區(qū)分。只有ASCII字符的文件,使用UTF-16編碼存在空間浪費(fèi)嚴(yán)重的現(xiàn)象(浪費(fèi)50%的存儲(chǔ)),由Ken Thompson(C語(yǔ)言發(fā)明人)和Robe Pike(Go語(yǔ)言發(fā)明人)提出的UTF-8編碼方案很快流行起來(lái)。UTF-8是單字節(jié)流,不存在字節(jié)序問(wèn)題,也不需要BOM。目前UTF-8是web通行標(biāo)準(zhǔn)。

對(duì)應(yīng)關(guān)系

USC-2的取值范圍是U+0000~U+FFFF,與UTF-8的對(duì)應(yīng)關(guān)系如下:

十六進(jìn)制 二進(jìn)制
0000 0000-0000 007F 0xxxxxxx
0000 0080-0000 07FF 110xxxxx 10xxxxxx
0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

從編碼可以看出,與二進(jìn)制相比,浪費(fèi)了很多空間。不過(guò)這也沒(méi)辦法,可顯示的字符更容易閱讀和理解,人類很難抗拒這個(gè)誘惑。

UTF-8轉(zhuǎn)換規(guī)則為: 1. 如果某字節(jié)第一位是 0 ,那么判定為 ASCII 字節(jié),除了 0 外余下的 7 位是 ASCII 碼,所以 UTF-8 是兼容 ASCII 碼的; 2. 如果第一個(gè)字節(jié)是 1 ,那么連續(xù)的幾個(gè) “1” 代表從這個(gè)字符開(kāi)始,后面連續(xù)的幾個(gè)字節(jié)其實(shí)是一個(gè)字位,且后面的字節(jié)都要以10開(kāi)頭。

了解如上規(guī)則,我們的程序便可輕松的處理UTF-8編碼的字節(jié)流。例如要找出“中”的UTF-8編碼,則可以這樣處理(注意文件是UTF-8編碼):

$char = "中";
$length = strlen($char);
$bytes = pack("a" . $length, $char);
echo "UTF-8:" . bin2hex($bytes) . "
";

// 或者
echo "UTF-8:";
for ($index = 0; $index < $length; ++ $index) {
    echo bin2hex($char{$index});
}
echo PHP_EOL;

也可以寫出針對(duì)UTF-8編碼的strlen函數(shù):

function myStrlen(string $string)
{
    $slen = strlen($string);
    $mlen = 0;
    $maxByteLength = 4;
    $maxOffset = 7;
    for ($i = 0; $i < $slen; ++ $i) {
        $byte = ord($string{$i});
        // 從01xxxxxx開(kāi)始對(duì)比,直到11110xxxx 10xxxxxx 10xxxxxx 10xxxxxx。只需要對(duì)比第一個(gè)字節(jié)即可
        for ($offset = 0; $offset < $maxByteLength; ++ $offset) {
            $result = $byte & (1 << ($maxOffset - $offset));
            if ($result === 0) {
                $i += $offset;
                ++ $mlen;
                break;
            }
        }
    }

    return $mlen;
}

$string = "Coder不是工程師!";
echo "mb_strlen:" . mb_strlen($string) . "
";
echo "mStrlen:" . myStrlen($string) . "
";

了解其原理,亂碼不再困惑和迷茫。

參考

https://www.cs.umd.edu/class/...

http://www.unicode.org/faq/ut...

https://my.oschina.net/goal/b...

http://mp.weixin.qq.com/s/2H6...

https://www.lifewire.com/file...

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/28373.html

相關(guān)文章

  • Linux下文件名長(zhǎng)度限制

    摘要:下文件名長(zhǎng)度限制出現(xiàn)場(chǎng)景在迭代中有一個(gè)需求是將文件名修改為所有班級(jí)的名稱集合,出現(xiàn)的班級(jí)過(guò)多導(dǎo)致的文件名過(guò)長(zhǎng)在下無(wú)法創(chuàng)建文件和文件夾的情況解決方式經(jīng)過(guò)查證,中文件名最長(zhǎng)為字符,文件路徑最大長(zhǎng)度為字符。這是被編碼方案決定的,通過(guò)來(lái)指定。 Linux下文件名長(zhǎng)度限制 出現(xiàn)場(chǎng)景:在迭代中有一個(gè)需求是將pdf文件名修改為所有班級(jí)的名稱集合,出現(xiàn)的班級(jí)過(guò)多導(dǎo)致的文件名過(guò)長(zhǎng)在linux下無(wú)法創(chuàng)建文...

    entner 評(píng)論0 收藏0
  • 徹底理解編碼

    摘要:只有徹底理解編碼,遇到編碼問(wèn)題才知道問(wèn)題的根源在哪里,并找到對(duì)應(yīng)的解決辦法?;ㄒ稽c(diǎn)時(shí)間去徹底消化并理解他,長(zhǎng)遠(yuǎn)來(lái)看,對(duì)以后工作效率的提升是非常值得的。比如中國(guó)就制定了等編碼規(guī)范。 只要涉及編程工作,編碼是永遠(yuǎn)繞不開(kāi)的問(wèn)題。只有徹底理解編碼,遇到編碼問(wèn)題才知道問(wèn)題的根源在哪里,并找到對(duì)應(yīng)的解決辦法。花一點(diǎn)時(shí)間去徹底消化并理解他,長(zhǎng)遠(yuǎn)來(lái)看,對(duì)以后工作效率的提升是非常值得的。下面是我對(duì)編碼的...

    guyan0319 評(píng)論0 收藏0
  • 徹底理解編碼

    摘要:只有徹底理解編碼,遇到編碼問(wèn)題才知道問(wèn)題的根源在哪里,并找到對(duì)應(yīng)的解決辦法?;ㄒ稽c(diǎn)時(shí)間去徹底消化并理解他,長(zhǎng)遠(yuǎn)來(lái)看,對(duì)以后工作效率的提升是非常值得的。比如中國(guó)就制定了等編碼規(guī)范。 只要涉及編程工作,編碼是永遠(yuǎn)繞不開(kāi)的問(wèn)題。只有徹底理解編碼,遇到編碼問(wèn)題才知道問(wèn)題的根源在哪里,并找到對(duì)應(yīng)的解決辦法?;ㄒ稽c(diǎn)時(shí)間去徹底消化并理解他,長(zhǎng)遠(yuǎn)來(lái)看,對(duì)以后工作效率的提升是非常值得的。下面是我對(duì)編碼的...

    leoperfect 評(píng)論0 收藏0
  • 前后端交互過(guò)程中的編碼

    摘要:前后端交互過(guò)程中涉及的編碼首先,瀏覽器的設(shè)置里有設(shè)置編碼格式,一般設(shè)置為。按照設(shè)置的順序檢查檢測(cè)文件的編碼。 起因 最近在寫PHP,本身對(duì)PHP不太熟練。然后遇到編碼這個(gè)問(wèn)題,困擾了大半天,索性,系統(tǒng)探索解決一番。 前后端交互過(guò)程中涉及的編碼 Browser cilent: 首先,瀏覽器的設(shè)置里有設(shè)置編碼格式,一般設(shè)置為UTF-8。 AJAX request: AJAX異步請(qǐng)求的過(guò)程...

    William_Sang 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<