[心得] UNICODE

看板Soft_Job (軟體人)作者 ( )時間3月前 (2023/11/06 13:26), 3月前編輯推噓19(19025)
留言44則, 23人參與, 3月前最新討論串1/1
寫嵌入式軟體,離人類世界遙遠,我只知道英文字ASCII code是1byte 小時候用倚天中文,BIG5編碼每個字2byte UNICODE似乎是2byte,可以表示全世界的文字,矇矇懂懂 閱讀Joel On Software的第四章 https://www.books.com.tw/products/0010467041 這篇文章也可以在這裡看到 https://www.cnblogs.com/AlphaAI/articles/3960296.html ---- 原來UNICODE有個Code Point的概念 制定(橋)出這張code point的前輩,真的是偉大的成就 人類終於有一個共同的表示法,紀錄每個字 所以用BIG5編碼的文件,可以讀入以後,"DECODE"成上述的編碼(我覺得是UCS2) 在wchar_t的domain (u16)做字串處理 最後儲存的時候,再"ENCODE"成其他格式,例如UTF-8 之前用Python的UNICODE感覺encode/decode難以理解 現在總算搞懂UTF-8是什麼,整理一份note記下來 https://lihgong.blogspot.com/2023/11/utf-8-unicode-utf-32-big5.html ---- patch, thanks to ybite, 更新UTF16 surrogate pair的資訊 這東西的概念是這樣 1. UNICODE 0xD800 ~ 0xDFFF大家講好不放東西;所以出現這種字元必定有詐! 一般狀態是 2byte代表一個字,這種狀態變成4byte代表一個字 很多地方都有類似的招數 2. 要把UNICODE的U+10000 ~ U+10FFFF編進去,先把數值扣掉0x10000 看看他在16bit定址範圍外的offset多少,這裡的值域是0xFFFFF, 20bit 3. 編碼規則如下 byte0 = offset[19:10] + 0xD800 byte1 = offset[9:0] + 0xDC00 4. 這種編碼結構好處是self-synchronization,因為開頭和結尾的值域固定下來了 如果中間有小錯誤也能偵測出來 缺點就LIB解析時,還有些額外的邏輯要弄,還真的有點麻煩; 不過比起用4byte字串的記憶體開銷相比,應該勉勉強強能接受; 反正現在電腦效能過剩,小事啦! ---- 後記3 感謝 *Dracarys 推薦的兩篇文章,過了20Y,和Joel當初的文章互相輝映! * https://tonsky.me/blog/emoji/ * https://tonsky.me/blog/unicode/ 原來UNICODE有Extended grapheme cluster A上面多帶一個圈,可以是U+00C5或是U+0041 U+030A 我看過芬蘭人的鍵盤,他們能打出某些特殊的上下標,亞洲人的我難以想像 所以A多帶個圈(兩個code point,符合我看他們鍵盤的感覺) 或是一個code point直接代表這個字,反應人類描述文字這件事,自帶的複雜度 直觀來看,所有文字都可以用UTF-32來表示?還是不行,有上述那些複雜的cases 所以作者說,處理UNICODE請用LIB,而且要按時更新的LIB(每年都會修訂) 以我來說,就是體認UNICODE有自帶的複雜度,不是像C的字串那麼簡單的東西 這兩篇文章確實看完就打通任督二脈,非常感謝 ---- 後紀4 關於UNICODE BOM (byte-order mark) 有個u16的數值,0xFE FF 這個數值用little-endian表示(大多數的電腦),在記憶體裡會是0xFF 0xFE 如果用big-endian表示,會是0xFE 0xFF 一份文件用UTF-16儲存,編輯器打開,不知道這份文件的endian 假如開頭是0xFF 0xFE,那就是little-endian 假如開頭是0xFE 0xFF,那就是big-endian 我覺得上面的例子很爛,因為FE/FF實在長得太相似 寫AA/BB可能更容易看清楚,不過標準就長這樣... 具體的資料可以看下面WIKI連結,有標準的BOM定義 https://reurl.cc/GKYxrW 另外更general的問題是,這兩種endian的好與壞,可以參考下面文章 https://hackmd.io/@chenishi/BJRaOrGCX?type=view 網路傳輸裡,先傳送big-endian天生是比較順的 比如有筆u32資料0xaabbccdd,傳輸協定規定從MSB to LSB做CRC 假如是little-endian的機器,那就得這樣灌入CRC 注意陣列的順序是倒置的... data[3](0xaa) -> data[2](0xbb) -> data[1](0xcc) -> data[0](0xdd) 如果這台機器是big-endian,這樣灌入CRC就很順了 data[0](0xaa) -> data[1](0xbb) -> data[2](0xcc) -> data[3](0xdd) 操起for-loop,big-endian就是順(直覺)很多 for(i=0; i<4; i++) { calc_crc(data[i]) } -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 61.220.100.151 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/Soft_Job/M.1699248406.A.A68.html

11/06 16:42, 3月前 , 1F
熱心推
11/06 16:42, 1F

11/06 23:40, 3月前 , 2F
11/06 23:40, 2F

11/06 23:41, 3月前 , 3F
有料分享就推
11/06 23:41, 3F

11/07 02:21, 3月前 , 4F
推 當初直覺該encode怎麼叫作decode 傻了一陣子 ORZ
11/07 02:21, 4F

11/07 11:40, 3月前 , 5F
推推推
11/07 11:40, 5F

11/07 15:49, 3月前 , 6F
11/07 15:49, 6F

11/07 17:32, 3月前 , 7F
Unicode 目前已經快破15萬字 無法塞進2byte了
11/07 17:32, 7F

11/07 17:41, 3月前 , 8F
因此UTF-16定義Surrogate Pair來解決(一個字32bit)
11/07 17:41, 8F

11/07 17:48, 3月前 , 9F
Python 2的時候str是ASCII 後來新增了unicode 型態
11/07 17:48, 9F

11/07 17:48, 3月前 , 10F
Python 3 其中一個大改就是str 一定是一串Unicode文字
11/07 17:48, 10F

11/07 17:49, 3月前 , 11F
(unicode扶正str)需要轉成特定編碼再.encode('utf-8')
11/07 17:49, 11F

11/07 17:50, 3月前 , 12F
encode出來的是bytes
11/07 17:50, 12F

11/07 17:52, 3月前 , 13F
然後傳統編碼 如big5 就是要建一張大表對應Unicode
11/07 17:52, 13F

11/07 17:52, 3月前 , 14F
也由於各種歷史原因 其實這個對應並沒有很完全做到1:1
11/07 17:52, 14F

11/07 17:55, 3月前 , 15F
如PTT的Big5日文 後來很長時間是用由but維護的「社群標準」
11/07 17:55, 15F

11/07 17:55, 3月前 , 16F
Unicode補完計畫來當對應表
11/07 17:55, 16F

11/07 17:56, 3月前 , 17F
直到後來PTT內建UTF-8編碼輸出模式後才解決很多問題
11/07 17:56, 17F

11/07 17:57, 3月前 , 18F
每個語言或每個作業系統都有自己內部存Unicode的規格
11/07 17:57, 18F

11/07 18:02, 3月前 , 19F
Python是PyUnicodeObject(PEP-393)
11/07 18:02, 19F

11/07 18:03, 3月前 , 20F
我還記得當年Python 2處理編碼真的是地獄
11/07 18:03, 20F

11/07 18:09, 3月前 , 21F
Unicode補完計畫最早是直接patch Windows 的cp950對應表
11/07 18:09, 21F

11/07 18:09, 3月前 , 22F
後來UTF-8變成壓倒性主流後 剩下PTT內部資料轉換的情境了
11/07 18:09, 22F

11/07 22:12, 3月前 , 23F
樓上好猛
11/07 22:12, 23F

11/07 23:04, 3月前 , 24F
11/07 23:04, 24F
※ 編輯: lihgong (122.116.164.102 臺灣), 11/07/2023 23:18:41

11/07 23:19, 3月前 , 25F
感謝*ybite,我把Surrogate Pair資訊也補上
11/07 23:19, 25F

11/07 23:41, 3月前 , 26F
啊不過同一個漢字不同寫法用同一個 code point 問題無解
11/07 23:41, 26F

11/07 23:45, 3月前 , 27F
然後難的地方在複雜語系一堆規則。
11/07 23:45, 27F

11/07 23:53, 3月前 , 28F
放棄UTF-16吧,投入可變字串長度UTF-8的世界
11/07 23:53, 28F

11/08 00:21, 3月前 , 29F
好文,學習了
11/08 00:21, 29F

11/08 05:13, 3月前 , 30F
11/08 05:13, 30F

11/08 09:13, 3月前 , 31F
再看完這兩篇就打通任督二脈了
11/08 09:13, 31F

11/08 09:13, 3月前 , 32F

11/08 09:13, 3月前 , 33F

11/08 09:28, 3月前 , 34F
優質文,推推
11/08 09:28, 34F

11/08 14:40, 3月前 , 35F
1
11/08 14:40, 35F

11/08 22:33, 3月前 , 36F
感謝分享
11/08 22:33, 36F

11/09 11:21, 3月前 , 37F
你應該是寫MCU之類的吧,Embedded Linux也是會碰Unicode
11/09 11:21, 37F

11/10 23:48, 3月前 , 38F
感謝 *Dracarys 我把您推薦的文章也補在後記上,非常讚
11/10 23:48, 38F
※ 編輯: lihgong (122.116.164.102 臺灣), 11/10/2023 23:59:30

11/11 00:29, 3月前 , 39F
看能不能再補充 BOM 的資訊? 系統常遇到這類問題.
11/11 00:29, 39F
※ 編輯: lihgong (122.116.164.102 臺灣), 11/11/2023 09:51:55

11/11 09:53, 3月前 , 40F
感謝 *kikilalagirl 我也順便搞清楚BOM和endian的優缺
11/11 09:53, 40F

11/12 06:55, 3月前 , 41F
之前碰的傳輸協定是小端傳輸,CRC 也是從小端開始
11/12 06:55, 41F

11/12 09:26, 3月前 , 42F
推推 最近接觸到bom utf-8 上網看了一下是什麼格式 就看到
11/12 09:26, 42F

11/12 09:26, 3月前 , 43F
原po撰文了
11/12 09:26, 43F

11/12 22:57, 3月前 , 44F
大推Dracarys的兩篇文章,不過閱讀順序應該反過來
11/12 22:57, 44F
文章代碼(AID): #1bI7aMfe (Soft_Job)
文章代碼(AID): #1bI7aMfe (Soft_Job)