[電腦] 字元編碼/解碼
===
###### tags: `學科`
###### tags: `學科`, `電腦`, `編碼`, `encode`, `encoding`, `解碼`, `decode`, `decoding`, `字元`, `char`, `字串`, `string`, `UTF-8`, `UTF8`, `UTF-16`, `CJK`, `BIG5`, `MS950`, `CP950`
<br>
[TOC]
<br>
## Python
### 將 unicode 字串轉成人類可讀字串
```
"\u6211\u8981\u627e\u4eca\u5e74\u5728\u65e5\u672c\u6ed1\u96ea\u7684\u7167\u7247".encode('utf-8').decode('utf-8')
```
執行結果:
```
'我要找今年在日本滑雪的照片'
```
<br>
## [中日韓統一表意文字](https://zh.wikipedia.org/wiki/中日韓統一表意文字)
### CJK Unified Ideographs (最常用)
- 最常用的漢字,是多數中文、日文和韓文用戶日常使用的基礎字符集
- 這個塊在Unicode中的範圍是 U+4E00 至 U+9FFF。它包含了約 20,971 個漢字,這些漢字涵蓋了現代東亞語言的基本漢字需求。
### CJK Unified Ideographs Extensions (擴充的漢字)
- **Extension A**:包含了6,582個額外的漢字,主要是一些罕見的、歷史上使用的或某些地方性文字。
- **Extension B**:這是一個非常大的擴展塊,包含了42,711個漢字。這些字符多用於專業文獻或歷史文獻,並且包括了一些非常罕見的字。
- **Extension C**:包含了4,149個漢字。
- **Extension D**:包含了222個漢字,主要添加了一些現代的或重新發現的漢字。
- **Extension E**:增加了5,762個漢字。
- **Extension F**:增加了7,473個漢字。
- **Extension G**:最新的擴展塊之一,增加了4,939個漢字。
<br>
<hr>
<br>
## 討論
### utf8 編碼後,最短幾碼?最長幾碼?
[ChatGPT4]
UTF-8 編碼是一種可變長度的字符編碼方式,用於編碼 Unicode 中的所有有效碼點。它的設計允許使用不同數量的字節來編碼不同範圍的字符:
1. **最短編碼長度**:1個字節。這用於編碼 U+0000 到 U+007F 之間的字符,即基本的 ASCII 字符集。這些字符只需一個字節就可以表示,其中第一位是 0,後面跟隨 7 位的 ASCII 碼。
2. **最長編碼長度**:4個字節。這用於編碼超出基本多語種平面(BMP)的字符,包括一些較少使用的符號和歷史文字。這些字符的碼點範圍從 U+010000 到 U+10FFFF。
UTF-8 的編碼機制如下:
- **1字節**:0xxxxxxx(用於表示範圍 U+0000 至 U+007F 的基本 ASCII 字符)
- **2字節**:110xxxxx 10xxxxxx(用於表示範圍 U+0080 至 U+07FF 的字符)
- **3字節**:1110xxxx 10xxxxxx 10xxxxxx(用於表示範圍 U+0800 至 U+FFFF 的字符,包括大多數常用的漢字等)
- **4字節**:11110xxx 10xxxxxx 10xxxxxx 10xxxxxx(用於表示範圍 U+10000 至 U+10FFFF 的字符)
因此,UTF-8 編碼的最短可能是 1 個字節,最長可能是 4 個字節。这使得 UTF-8 非常靈活,能夠有效地編碼各種語言的文字,同時仍保持與 ASCII 的向後兼容性。
<br>
### [226, 128, 140, 216, 167, 219, 140]
- ### Question
怎麼區分 utf8 字節?
- ### ChatGPT4
要正確解析 UTF-8 編碼的字節序列,您需要根據 UTF-8 的字節序列規則來識別每個字節或字節組合的角色。在 UTF-8 中,每個編碼單元的第一個字節會告訴你後續有多少字節與它相關聯,以形成完整的 Unicode 字符。以下是如何根據首字節來識別 UTF-8 字節序列的詳細步驟:
1. 單字節字符(0xxxxxxx):如果字節的最高位為0,那麼這個字節代表一個字符,範圍是 U+0000 到 U+007F。
2. 多字節字符:如果字節的最高位是 1,那麼首字節的連續1的數量將指示該字符由多少字節組成:
- 2字節字符(110xxxxx 10xxxxxx)
- 3字節字符(1110xxxx 10xxxxxx 10xxxxxx)
- 4字節字符(11110xxx 10xxxxxx 10xxxxxx 10xxxxxx)
根據您提供的字節序列 [226, 128, 140, 216, 167, 219, 140],讓我們逐個字節解析:
1. **226 (11100010)**:這是一個 3字節字符的首字節,因為首字節的格式是 1110xxxx。
2. **128 (10000000)**:這是續字節,格式為 10xxxxxx,表示它是上一個首字節的一部分。
3. **140 (10001100)**:這同樣是續字節,格式為 10xxxxxx,與前兩個字節一起表示一個字符。
這三個字節(226, 128, 140)合在一起編碼一個字符。
4. **216 (11011000)**:這是一個 2字節字符的首字節,因為首字節的格式是 110xxxxx。
5. **167 (10100111)**:這是續字節,格式為 10xxxxxx,表示它是上一個首字節的一部分。
這兩個字節(216, 167)合在一起編碼另一個字符。
6. **219 (11011011)**:這是又一個 2字節字符的首字節。
7. **140 (10001100)**:這是續字節,格式為 10xxxxxx。
最後這兩個字節(219, 140)合在一起編碼最後一個字符。
總結起來,這個字節序列包含三個字符,由三個字節、兩個字節和兩個字節的組合依次編碼。
<br>
### "🦙" 在 javascript 的編碼
- ### 使用 python 讀取測試
```python=
s='🦙'
len(s) # 1
hex(ord(s[0])) # '0x1f999'
bin(ord(s[0])) # '0b11111100110011001'
s[0].encode('utf8') # b'\xf0\x9f\xa6\x99'
s[0].encode('utf16') # b'\xff\xfe>\xd8\x99\xdd'
s[0].encode('utf-16-le') # b'>\xd8\x99\xdd'
```
- ### Question-1
javascript 是使用什麼編碼?
"🦙" 被編碼成'\uD83E' + '\uDD99'
- ### ChatGPT4
JavaScript 使用 UTF-16 編碼來表示 Unicode 字符。在 UTF-16 編碼中,字符可以使用一個或兩個 16 位的單位來表示。對於較常見的字符,使用單個單位就足夠了,但對於超出基本多語言平面的字符,則需要使用兩個單位,這種配對稱為「替代對」(surrogate pair)。
例如,你提到的字符 "🦙"(一隻羊駝),在 Unicode 中的碼位是 U+1F999。因為這個碼位超出了基本多語言平面(U+0000 至 U+FFFF),所以在 UTF-16 中它被編碼為一對替代碼單位:'\uD83E' 和 '\uDD99'。這裡,'\uD83E' 是高位替代碼(high surrogate),而 '\uDD99' 是低位替代碼(low surrogate)。這兩個單位組合起來代表了原始的 Unicode 碼位 U+1F999。
- ### Question-2
Python 中如何將一個字元"🦙"轉成JavaScript的編碼?
- ### ChatGPT4
在 Python 中,您可以使用內建的方法來將任何 Unicode 字元轉換成 JavaScript 的 UTF-16 編碼形式。對於字元 "🦙",我們可以將其編碼為 UTF-16 的替代對,並將這些碼點格式化為 JavaScript 可識別的形式。以下是如何操作的步驟:
獲取字元的 UTF-16 編碼(將返回一對替代碼)。
將這些編碼轉換為 JavaScript 可接受的字符串形式。
我將展示如何實現這一點:
```python=
# 要轉換的字元
char = "🦙"
# 獲取 UTF-16 編碼的替代對
encoded = char.encode('utf-16-le') # LE 代表小端格式
# 將字節數據轉換為 16 位整數列表
codes = list(int.from_bytes(encoded[i:i+2], 'little') for i in range(0, len(encoded), 2))
# 格式化為 JavaScript 字符串形式
js_encoding = ''.join(f'\\u{code:04X}' for code in codes)
print(js_encoding) # 備註:\uD83E\uDD99
```
這段 Python 代碼首先將 "🦙" 轉換成 UTF-16 編碼的字節串,然後解釋為一系列 16 位整數,最後將這些整數轉換成 JavaScript 的轉義字符串格式。這樣,你就可以在 JavaScript 程式中直接使用這個編碼了。
<br>
### 台灣常用編碼是 Big5 (MS950 / CP950),大陸常用編碼是?
[ChatGPT4]
大陸常用的編碼是 GB2312,以及它的擴展版本 GBK 和 GB18030。GB2312 主要涵蓋了簡體中文字符,而 GBK 和 GB18030 則包括了更多的漢字和符號,以支持多種語言和符號,進而達到更全面的兼容性和應用範圍。GB18030 是目前大陸官方推薦的標準編碼,它也保證了向下與 GBK 及 GB2312 的兼容。
<br>
### 日文常用編碼是?
[ChatGPT4]
日文常用的編碼方式主要有以下幾種:
1. **Shift_JIS**:
這是一種日文編碼方式,於1983年由微軟和ASCII公司共同開發。它被廣泛用於Windows系統中的日文處理,並且在日本的許多應用程序和數據庫中仍然非常普遍。
2. **EUC-JP**:
這是“Extended Unix Code”的日本語版本,主要用於Unix和類Unix系統中的日文處理。它支持更多的漢字和符號,並且在日本的許多伺服器和網絡應用中被使用。
3. **ISO-2022-JP**:
這是一種在電子郵件和一些網路協定中常用的日文編碼。它支持在ASCII和多種日文字符集之間切換,使得它在需要傳輸ASCII和日文混合內容的場景中特別有用。
4. **UTF-8**:
隨著全球化和多語言支持的需求增加,UTF-8已成為包括日文在內的多種語言編碼的國際標準。它能夠處理世界上幾乎所有的語言和符號,因此在新的應用程序和網站開發中極為常用。
這些編碼各有其特點和使用場景,選擇哪一種通常取決於特定的應用需求和系統兼容性。
<br>
### UTF-8 編碼,如何判斷一個字元是 繁體字?還是簡體字?如:「电」是簡體字,「電」是繁體字
[ChatGPT4]
在UTF-8編碼下,自動識別一個字元是否為繁體字或簡體字並不是直接通過編碼本身來實現的,因為UTF-8是一種對Unicode字元的編碼方式,並不直接區分繁簡體。要判斷一個中文字元是繁體還是簡體,通常需要進行以下幾種方法:
1. **字典對照法**:這是最直接也是最常用的方法。通過一個包含繁體和簡體字對照的字典,你可以查找每個字元對應是否存在於繁體或簡體字集中。例如,查找「電」在繁體字字典中,而「电」在簡體字字典中。
2. **語言庫支持**:一些編程語言或工具庫支持語言特性識別,可以用來判斷字元的繁簡體。例如,Python 中可以使用第三方庫如`hanziconv`來轉換及判斷繁簡體。
3. **規則判斷法**:對於一些有固定轉換規則的字元,比如「電」和「电」,可以建立一個簡單的規則庫來直接判斷。不過,這種方法對於一些繁簡一字多形或者不常見的字元可能不夠準確。
4. **機器學習方法**:對於大量的文本數據,可以透過訓練機器學習模型來識別文本中的語言特性,進而判斷繁簡體。這需要大量的訓練數據和一定的技術支持。
在實際應用中,選擇哪種方法取決於具體需求和可用資源。字典對照法因其簡單直觀而被廣泛使用,特別是在需要高準確度的場合。
<br>
### 透過 python 對「电」進行編碼成 "gb2312",如果成功,表示簡體字
```python=
"电".encode("gb2312")
"電".encode("gb2312")
```
這樣作法是否恰當?
[ChatGPT4]
您提到的方法確實可以用來判斷一個漢字是否是簡體字,但是它有一些局限性。當您嘗試將中文字元編碼成 "gb2312",如果編碼成功,這通常表示該字元屬於簡體中文字符集(因為GB2312主要包含了簡體中文字符)。如果編碼失敗(拋出異常),這可能表示該字元不在GB2312的字符集中,通常意味著它是繁體字或者不在該簡體字編碼範圍內。
#### 示例代碼
您的代碼示例:
```python
try:
"电".encode("gb2312")
print("「电」是簡體字")
except UnicodeEncodeError:
print("「电」不是簡體字")
try:
"電".encode("gb2312")
print("「電」是簡體字")
except UnicodeEncodeError:
print("「電」不是簡體字")
```
這段代碼會試圖將「电」和「電」編碼為GB2312。由於「电」可以被成功編碼,它會被識別為簡體字。相反,「電」在GB2312中沒有對應的編碼,會拋出一個UnicodeEncodeError異常,從而識別它為非簡體字。
#### 局限性
1. **不完整的繁簡對應**:某些繁體字也可能存在於GB2312字符集中,特別是那些同時被視為繁體和簡體的共用字。此方法對於這些字元可能無法準確判斷。
2. **字符集範圍限制**:GB2312只包含常用的簡體中文字符,對於一些罕見的簡體字或更新的字元可能無法進行編碼。
儘管有這些局限性,這種方法對於快速篩選大部分常見的簡體字是有效的。如果您的應用場景不需要考慮上述特殊情況,這可以是一種實用的解決方案。
#### [補充] 不完整的繁簡對應情況:
```python=
>>> "手".encode("big5") # 繁體字
b'\xa4\xe2'
>>> "手".encode("ms950") # 繁體字
b'\xa4\xe2'
>>> "手".encode("cp950") # 繁體字
b'\xa4\xe2'
>>> "手".encode("gb2312") # 簡體字
b'\xca\xd6'
>>> "手".encode("gb18030") # 簡體字
b'\xca\xd6'
>>> "手".encode("shift_jis") # 日文漢字
b'\x8e\xe8'
```
- 「手」字元同時存在多種編碼系統中
<br>
### 有 CJK-I, CJK-2 嗎?
[ChatGPT4]
沒有官方稱為 "CJK-I" 或 "CJK-2" 的編碼標準。可能您所提到的是某種對常見的 **CJK(Chinese, Japanese, Korean)**字符集的非正式簡稱或是特定軟體、文檔中的用語。
通常在討論與CJK相關的字符集時,會涉及以下幾種標準:
1. **Unicode**:現今最普遍使用的編碼標準,包含了所有CJK字符的統一表示。
2. **GB 2312, GBK, GB18030**:這些是針對中文(主要是簡體)的字符集。GB18030是目前中國大陸的標準,兼容早期的GB2312和GBK,並包含了更多字符。
3. **Big5**:是針對繁體中文的編碼標準,主要在台灣和香港地區使用。
4. **JIS, Shift_JIS, EUC-JP**:這些是日本使用的主要編碼標準。
5. **KS X 1001, EUC-KR**:這些是韓國使用的主要編碼標準。
如果您所指的是某個特定的概念或標準,可能需要更詳細的上下文來確定具體是哪一種編碼或標準。在Unicode的框架中,有時會根據字符的範圍和分布將CJK字符劃分為不同的區塊,如"CJK Unified Ideographs"、"CJK Unified Ideographs Extension A"等,但這些分類與"CJK-I"或"CJK-2"並不直接相關。
<br>
### 那 CJK Unified Ideographs Extension I 又是?
[ChatGPT4]
在Unicode標準中,有多個擴展塊專門用於包含更多的CJK統一表意文字(漢字),這些塊稱為“CJK Unified Ideographs Extensions”。這些擴展塊被設計來補充基本的“CJK Unified Ideographs”塊,以包含更多歷史上使用的漢字以及某些特殊用途的漢字。
"CJK Unified Ideographs Extension I" 並非一個正式的Unicode塊名稱。如果您指的是像 "Extension A"、"Extension B" 這樣的具體擴展塊,這些塊分別包含了不同的漢字集合。以下是一些主要的擴展塊及其用途:
1. **Extension A**:包含了6,582個額外的漢字,主要是一些罕見的、歷史上使用的或某些地方性文字。
2. **Extension B**:這是一個非常大的擴展塊,包含了42,711個漢字。這些字符多用於專業文獻或歷史文獻,並且包括了一些非常罕見的字。
3. **Extension C**:包含了4,149個漢字。
4. **Extension D**:包含了222個漢字,主要添加了一些現代的或重新發現的漢字。
5. **Extension E**:增加了5,762個漢字。
6. **Extension F**:增加了7,473個漢字。
7. **Extension G**:最新的擴展塊之一,增加了4,939個漢字。
這些擴展塊的存在顯示了Unicode如何逐步擴充來包含更多全球範圍內使用的字符,特別是考慮到漢字的廣泛使用和歷史深度。這些擴展塊使Unicode能夠支持包括文獻學者、語言學家和其他專業人士在內的用戶對這些字符的需求。
<br>
### CJK Unified Ideographs Extensions 的主要常見字 (即主體,非Extensions部份),又叫什麼?
[ChatGPT4]
CJK Unified Ideographs Extensions 的主要常見字部分,在Unicode中簡稱為 CJK Unified Ideographs。這個塊包含了最常用的漢字,是多數中文、日文和韓文用戶日常使用的基礎字符集。
#### CJK Unified Ideographs 詳細說明:
- **範圍**:這個塊在Unicode中的範圍是 U+4E00 至 U+9FFF。它包含了約 20,971 個漢字,這些漢字涵蓋了現代東亞語言的基本漢字需求。
- **用途**:這些漢字是中文(簡體和繁體)、日文、韓文常用的漢字。這個塊的字符在東亞地區的文檔、書籍、網頁和其他媒介中非常常見。
這個Unicode塊的存在是為了支持中日韓三國之間漢字的共享和標準化,使得相同的漢字在不同語言系統中能夠有一致的編碼,從而便於計算機系統的處理和跨語言的資訊交流。除了這個主塊之外,隨著時間的推移和對更多漢字的需求,Unicode逐步增加了多個擴展塊來包含更多罕見或特殊用途的漢字。