登錄站點

請由此登入

技術敎學 - 自定義風格

  • 虫二

    何謂編碼(Encoding) ?

    虫二 2013-06-05 01:48

    編碼 (Encoding)


    A. 電腦編碼系統簡介:

    電腦系統中資料儲存的最基本單位是「位元 (bit)」,而每個「位元」所
    能代表的數值只有 0 與 1 而已。因此當我們要用電腦做資料的儲存與處理時,
    我們通常會將連續幾個位元和起來看成一個單位,稱之為「位元組 (byte)」,
    其所能代表的數值就不會只限於 0 與 1,而可以達到 2^n-1 (其中 n 為該位
    元組中所包含的位元個數),如此我們就可以將我們想記錄在電腦系統的符號
    一一編號,以位元組為單位儲存在電腦中,這就是編碼 (Encoding) 的基本觀念。

    由於早期的電腦系統是發源於美國,因此最早的編碼系統也是發源於此。由於
    他們的資料只需數字、26 個英文字母 (包括大小寫)、標點與其他特殊符號、
    外加一些電腦系統的控制碼即可,因此當時一個位元組的大小只需 7 個位元
    即可包含所有所需的資訊,總共可容納 128 個符號,這也就是大家所熟知的
    ASCII 編碼。

    然而對於歐洲語系而言,7 個位元的編碼空間不符合所需,因為除了 26 個英
    文字母外,歐洲許多國家還需要拉丁字母、特殊字母的上下標與其他符號等,
    才能完整表示他們的語言。因此原來的編碼系統必須再擴充,由 7 個位元變
    為 8 個位元,以容納那些多出的符號,這就是 ISO8859 的編碼標準。而依地
    區語系的不同, ISO8859 的編碼標準又分成幾個部分,例如 ISO8859-1 所包
    含的符號可使用於英語、丹麥語、芬蘭語、德語 .... 等,而 ISO8859-2 則
    可用於英語、德語、羅馬尼亞語、波蘭語 .... 等。每一個部分的 0-127 碼
    的編碼方式與 ASCII 都是一樣的,只有在 128-255 碼才依地區不同而不同。
    如此不同地區的人們可以選用不同部分的 ISO8859 編碼來處理他們的資料。

    然而到了亞洲地區,上述的 8 位元編碼又不夠用了。因為亞洲地區不再是拼
    音文字,因此多出了成千上萬個符號,我們已無法仿照當初 ISO8859 的做法,
    弄出屬於中文的部分,或屬於日文的部分。唯一的作法只有合併幾個位元來
    共同表示一個符號,如此才有足夠的空間來容納一個地區所有的文字。例如
    我們台灣地區最常見的 BIG5 編碼,就是將兩個位元組合起來看成一個字。
    但當一份文件中同時要有中英文時,意味著我們要有一個規則可以區分這個
    位元組應該視為 ASCII 碼,或者它與它的下一個位元組應合起來視為一個
    BIG5 碼。為了定出這樣的規則,就表示說我們無法全部使用整個雙位元組
    的所有空間 (共 65536 個值)。就如我們的 BIG5 碼,其所包含的字數就只
    有 13000 多個。

    以上就地區語文使用似乎已經足夠了,然而在某些場合下,我們仍需要在同
    一份文件中記錄多國文字。以 BIG5 編碼為例,它可以確保中文字與 ASCII
    碼可以同時存在,不至於混餚 (事實上對於其他語系而言,他們的編碼方式多
    半都是如此: 可以讓該地區的文字與 ASCII 碼同時存在),但如果我們要同時
    表示中文、日文、韓文的文字呢?這裡就真正牽涉到多國語文的編碼範籌了。
    而編碼系統的擴充就有兩種形式:

    1. 文法式 (Modal) 編碼系統:

    這裡最有名的就是 ISO2022 編碼。它的特徵是讓一個字串有「狀態」的區
    別,而不同「狀態」的改變則以幾個特殊位元組值來代表。例如當一個字串
    中讀到了位元組值 a 與位元組值 b 時,就表示字串進入狀態一,若讀到位
    元組值 a 與 c 時就表示字串進入狀態二 .... 等。然後我們可以定義狀態
    一以後的字串應解釋為日文 JIS 編碼,狀態二以後應解釋為簡體中文的 GB
    編碼 .... 等等。如此便可以有系統地將各國的編碼方式整合進來。

    很明顯的,這樣的編碼方式有一個限制,就是可以整合進來的編碼系統不能
    與狀態改變標記位元 (如上例的 ab, ac .... 等) 衝突,否則的話就無法
    整合進來。我們的 BIG5 編碼就是因為衝突了,所以無法整合到 ISO2022 中。
    而且,這樣的編碼方式很複雜,程式實作困難,因此近年來較少有人使用了。

    2. 定長式編碼系統:

    此編碼系統是仿照 ASCII、ISO8859 的概念,給定一個固定長度的位元數,
    試圖將世界上所有的符號都包含進來,並依序給它們編號。此方式最著名的
    就是 Unicode (或稱 UCS2) 與 UCS4。以 Unicode 為例,其每個「位元組」
    的長度固定為 16 個位元,即拿兩個傳統 8 位元的位元組合併成一個新的位
    元組,然後編號從 0 到 65535 全部拿來使用,其中 0 到 127 是與 ASCII
    碼相容的。如此方式,大概可以包含世界上主要的語言與符號如歐美地區、
    中日韓越、中亞地區 .... 等等。至於 UCS4 則是 Unicode 的再擴充,其每
    個「位元組」有 32 個位元,其中 0 到 65535 是與 Unicode 相同的,其餘
    則是用來編入世界其他少數語言與罕用文字。

    此編碼方式很明顯的好處就是沒有了文法式編碼系統的限制,同時程式容易
    實作,只要提供一個適當的轉碼表,我們就可以很容易地將地區常用編碼系
    統轉換為 Unicode 或 UCS4。此轉碼表可能相當大,特別是在繁體中文的
    情況,但對於目前電腦系統的能力 (記憶體容量與運算速度 .... 等) 而言
    已不是問題。因此,此編碼方式也逐漸成為世界的主流。儘管在某些地區仍
    然對此編碼方式有意見,但在可預見的未來它將會越來越普遍。

    然而,定長式編碼系統並非完全沒有限制的。最明顯的一點就是目前的電腦
    硬體與程式語言都是將一個「位元組」定義為 8 個位元長,而非 16 或 32
    個位元長,而且考慮到相容性的問題,在可預見的未來恐怕不會有全面性的
    改變。同時由於不同 CPU 對於「位元序」的解釋不同,使得同樣是 16 或 32
    位元的一個數值,在不同的 CPU 下會呈現不同的值 (例如 32 位元下在 x86
    CPU 所呈現的數值 1,若將同樣的位元資料移到其他 RISC CPU 下可能呈現
    出 16777216)。因此定長式編碼多半只能用於正執行中的程式內部,以便
    於資料處理。若程式需要做資料的輸出入時,最理想的方式是將它轉為適當
    的「多位元組編碼」 (見後述) 然後才進行。


    B. GNU/Linux 下的編碼與字集:

    在很多情況下,我們經常將「編碼 (Encoding)」與「字集 (Character Set)」
    混為一談,但實際上它們各自有明確的定義的。所謂的「字集」是一組符號
    (或文字) 的集合,而「編碼」則是將這一組符號 (或文字) 以適當的方式編
    入位元組中,以便電腦能夠表示與儲存。在許多情況下,由於一個編碼方式所
    能容納的字數是有限的,也因此就限定了它所能使用的「字集」,故有時我們
    會將「編碼」與「字集」視為同一個東西。

    在使用 glibc-2.2.X 系列的 GNU/Linux 系統中,由於已完整支援了 I18N 架
    構,使得世界各地的語系資料庫都已完整地建立在系統底層的函式庫 (libc)
    中,這其中也包含了各語系所用的字集與其相對應的編碼系統。以我們中文為
    例,兩岸三地可能會常用到的編碼系統包括:

    1. BIG5: 台灣地區最常見的編碼方式。目前 glibc 中的 BIG5 是以微軟公司
    所定義的 CP950 為基礎,外加文鼎公司所採用的倚天外字集與 Unicode
    轉換表而成。

    2. EUC-TW: 此編碼即等價於教育部所編定的 ISO10646 國家標準編碼,目前
    已內含了所有與 UCS4 可以互轉的中文字,其他尚未定義與 UCS4 可互
    轉的中文字則要等定義完成後才會納入。

    3. BIG5HKSCS: 此為香港地區所使用的 Big5 與香港政府增補字集。它與 BIG5
    編碼是相容的,並加以擴充以容納其他罕用字。

    4. GB2312: 此為大陸地區最通行的編碼方式,可容納常用的簡體字集。

    5. GBK: 此為 GB2312 的擴充,除了容納原本 GB2312 中的簡體字以外,同時
    還包含了繁體字與其他罕用字。

    6. GB18030: 此為最近新定義出的字集編碼,與 GB2312 相容。

    7. Unicode 與 UCS4: 其中 UCS4 在 GNU/Linux 系統中被用作轉碼系統的「基
    底字集」(見後述)。

    8. UTF-8: 此為 Unicode 的多位元編碼形式,可用於 Unicode 編碼的輸出。

    以上的編碼系統在 GNU/Linux 中都有完整的支援,至於教育部新定的 Big5+
    目前則不在支援之列。


    C. GNU/Linux 的轉碼系統:

    在具備完整的 I18N 環境支援的 UNIX 系統中 (包括 GNU/Linux 系統),其編
    碼系統的轉換有兩種方式:

    1. 一般轉換介面: 此即為 libc 中的 iconv() 編碼轉換介面,它可以做到各
    種編碼的轉換。然而,在一般的 UNIX 系統中,並不見得系統同時支援編碼
    系統 A 與編碼系統 B, 就一定能做到 A 與 B 之間的互轉,即使 A 與 B
    內含相同的 (子) 字集。但在 GNU/Linux 底下,只要 A 與 B 內含相同的
    (子) 字集,則可以直接透過 iconv() 做轉換。例如將 BIG5 轉成 BIG5HKSCS
    或反過來,或者 GB2312 與 GBK 與 GB18030 之間的互轉。當然,各字集與
    UCS4 之間的互轉都不是問題,原因就是 glibc 是以 UCS4 做為轉碼系統的
    「基底字集」。

    所謂的「基底字集」意指各地區的語文符號在系統內部的表式方式,而且它
    還是各地區所有語文符號的集合。根據此定義,表示我們可以將世界各地所
    有的編碼方式轉換成「基底字集」來統一處理 (理論上)。而 glibc 所採用
    的「基底字集」的編碼方式就是 UCS4, 它是定長編碼系統,採用 32 位元
    的位元組來編碼,它是目前已定義最大的一個字集的編碼方式,而且它仍持
    續擴編世界各地的文字與符號。

    在 GNU/Linux 下如果要透過 iconv() 進行轉碼工作時,它實際上是先將該
    編碼轉成基底字集,然後再轉成目的編碼,如此便二確保只要編碼中有共同
    的 (子) 字集時,轉換可以順利進行。

    便對於沒有共同子字集的情況呢?例如 BIG5 與 GB2312 之間的互轉,在
    GNU/Linux 下也提供額外的 iconv() 模組來進行,而這些都統一在 iconv()
    介面之下,故在實際使用上不會感到任何差別。然而這類的額外模組目前
    並未包含所有可能的轉換情況,但仍持續在建構中。例如 BIG5 與 GB2312
    的互轉模組已於日前完成,目前尚在實驗版的 glibc-2.3 測試中,預計不
    久的未來等 glibc-2.3 正式發表,並且大部分的 GNU/Linux 系統都換裝
    glibc-2.3 之後,中文繁簡轉換的部分將不是問題。

    2. 區域資料庫編碼轉換介面: 此轉換介面是與系統區域化資料庫 (locale) 相
    關的,也是絕大部分的 I18N 程式會使用的介面。由於不同的區域化資料庫
    所採用的編碼系統是固定的,例如我們台灣地區的區域化資料庫名稱為
    zh_TW (或 zh_TW.Big5), 其採用的編碼系統即為 BIG5。而區域化資料庫主
    要的任務只有在讓同一份程式碼可以處理各地區的語言,因而可以適用於各
    地區,而不需要額外修改程式本身,故它的任何不在於處理多國語文的問題。
    因此,這個轉碼介面只負責該資料庫所採用的編碼,與系統基底字集所採用的
    編碼系統互轉而已。它不包含如上述 iconv() 轉碼介面那樣,可以做到任意
    編碼系統間的互轉。

    此轉碼介面最大的用途在於方便程式做文字處理。因為地區原本的編碼系統
    多半是採用「多位元組」編碼方式,例如 BIG5 就是將兩個 8 位元的位元組
    組合起來使用,故稱「多位元組編碼」。但當我們要在字串中區分中文字與
    英文字母時就會遇到麻煩,因為前者是以兩個位元組來代表,後者確是以單
    一一個位元組來代表,故我們要在程式中額外寫入 BIG5 碼的編碼規則才行,
    而這樣的程式就不能適用與其他的編碼方式了。因此,當我們用此轉換介面
    將它轉成定長編碼方式時,由於每個字 (不論中英文) 都是故定的長度 (即
    位元組數),我們稱之為「寬字元 (wide character)」,這使得我們可以很
    方便做字串處理。同時,我們的程式中也不必加入 BIG5 的編碼規則,因為
    這些都在此轉碼介面中處理掉了,因此,這樣寫出來的程式就是一個支援 I18N
    的程式,可以在不需要修改程式碼本身的情況下適用於各語系與編碼系統。

    然而,我們在前面也提過,定長編碼方式 (即寬字元) 只能用於運作中的程式內部,
    如果在做資料輸出入時可能因 CPU 的位元序不同與各硬體系統的限制而出錯。因此,
    當我們要做資料交換時,最好的方式是將它轉回多位元組編碼,才能確保不會有問
    題。這在第 2 點的轉換介面是不成問題的,因為基底字集與其多位元組編碼之間
    的對應是定義在區域化資料庫中的;但在第 1 點的轉換介面中,特別是 Unicode
    或 UCS4,而且包含了如中日韓等多國語文資料的情況又如何呢?對於 Unicode
    而言,其所對應的多位元組編碼為 UTF-8, 它可以將所有 Unicode 碼轉換成不定
    長度的位元組,視其 Unicode 碼值而定,而且轉出來的多位元組與 ASCII 編碼相
    容,故可以適用於所有的 UNIX 應用程式。至於 UCS4 所對應的多位原組編碼則為
    UTF-16, 它是將兩個 UTF-8 字元組合而成的。

你還不是該群組正式成員,不能參與討論。 現在就加入