」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > Unicode、表情符號和一點 Golang

Unicode、表情符號和一點 Golang

發佈於2024-11-01
瀏覽:228

Unicode, Emojis, and a bit of Golang

最近,我的 Fedora Linux 安装在操作系统 UI 和浏览器中显示表情符号时遇到了问题。这个问题促使我对字体配置项目进行了一些调查,但为了测试我的配置和字体,我需要从所有 Unicode 版本生成表情符号,这最终导致我编写了一个 Golang“脚本”来打印所有表情符号和一些表情符号有关其内部结构的信息。

在这次旅行中,我深入研究了表情符号的内部结构、它们的二进制表示形式,以及 Unicode 标准关于表情符号做出的一些奇怪/可爱的决定。

但首先,让我们快速退后一步,总结一些术语表。

编码(或字符编码)

我们可以将编码描述为语言的字母和该字母的二进制表示之间的“映射”或“翻译”。例如,传统的 ASCII 编码将字母 a 映射为十六进制 0x61(二进制 0b01100001)。编码示例包括 Microsoft (Windows 125x) 或 ISO (ISO/IEC 8859) 8 位代码页。

在这些固定的 8 位代码页中,使用的最小信息“量”是 8 位(1 字节),这意味着它们可以包含 256 个不同的字母/字符。通过重用 256 个二进制代码创建不同的代码页来支持多种语言。因此,在一个文本文件上写入这 3 个字节 [0xD0、0xE5、0xF2],使用希腊语 ISO 8859-7 读作“Πες”,或使用西方 ISO 8859-7 读作“Ðåò”(相同字节,解释不同)基于代码页)。

在某些时候,随着技术的进步,拥有许多不同的代码页并不能很好地扩展。因此,我们需要能够适合所有语言(以及更多语言)并且跨系统统一的东西。

[快进,留下大量历史和标准,到现在]

统一码标准

Unicode 标准旨在支持世界上所有可以数字化的书写系统。因此,使用上面的示例,在 Unicode 标准中,希腊字母“Π”的代码为 0x03A0,而拉丁大写字母 eth“Д的代码为 0x00D0,并且不再冲突。 Unicode 标准有多个版本,在撰写本文时,最新版本是 16.0(规范)。

但是等一下,这个“代码点”是什么?

Unicode 代码点

在 Unicode 标准中,每个“字母”、控制字符、表情符号和每个定义的项目通常都有一个唯一的二进制值,称为“代码点”。该标准定义了所有代码点,每个代码点都包含纯代码/二进制信息。每个代码点的十六进制格式通常以 U 前缀编写。例如,希腊小写字母 Omega (ω) 代码点是 U 03C9。

那么我们实际上由谁来编码这些代码点?

Unicode 编码形式和编码方案

将代码点编码为字节的第一部分是编码格式。根据标准:

编码形式指定如何将 Unicode 字符的每个整数(代码点)表示为一个或多个代码单元的序列。

编码形式使用术语“代码单元”来指代用于表示特定编码内的 Unicode 代码点的最小数据单元。

Unicode 标准定义了三种不同的编码形式:

  • UTF-32。每个代码点的固定长度代码单元。每个代码点的大小:一个 32 位代码单元(4 字节)。
  • UTF-16。每个代码点的可变长度代码单元。每个码点的大小:1个或2个16bit码单元(2~4字节)。
  • UTF-8。每个代码点的可变长度代码单元。每个码点的大小:1到4个8bit码单元(1~4字节)。

这意味着根据所使用的编码形式,单个代码点或一系列代码点可能会进行不同的编码。

负责 Unicode 中实际二进制序列化的层称为编码方案,负责所有低级细节(例如字节序)。 Unicode 规范表 2-4:


|Encoding Scheme| Endian Order                | BOM Allowed? |
| ------------- | ----------------------------| ------------ |
| UTF-8         | N/A                         | yes          |
| UTF-16        | Big-endian or little-endian | yes          |
| UTF-16BE      | Big-endian                  | no           |
| UTF-16LE      | Little-endian               | no           |
| UTF-32        | Big-endian or little-endian | yes          |
| UTF-32BE      | Big-endian                  | no           |
| UTF-32LE      | Little-endian               | no           |


注意:几乎所有现代编程语言、操作系统和文件系统都使用 Unicode(及其编码方案之一)作为其本机编码。 Java和.NET使用UTF-16,而Golang使用UTF-8作为内部字符串编码(这意味着当我们在内存中创建任何字符串时,它都会以上述编码形式以Unicode编码)

表情符号

Unicode 标准还定义了表情符号(很多)的代码点,并且(在与版本号混淆之后),表情符号“标准”的版本与 Unicode 标准并行发展。在撰写本文时,我们有表情符号“16.0”和 Unicode 标准“16.0”。

示例:
⛄ 没有雪的雪人 (U 26C4)
?笑脸笑眼三颗心 (U 1F970)

表情符号修饰符和加入

Unicode 定义了可以遵循表情符号基本代码点的修饰符,例如变体和肤色(我们不会探讨变体部分)。

我们有六种肤色修饰符(遵循 Fitzpatrick 等级),称为 EMOJI MODIFIER FITZPATRICK TYPE-X(其中 x 为 1 到 6),它们会影响所有人类表情符号。

浅肤色 (Fitzpatrick Type-1-2) (U 1F3FB)
中浅肤色 (Fitzpatrick Type-3) (U 1F3FC)
中等肤色 (Fitzpatrick Type-4) (U 1F3FD)
中深肤色 (Fitzpatrick Type-5) (U 1F3FE)
深色肤色 (Fitzpatrick Type-6) (U 1F3FF)

那么,例如,像所有人类表情符号一样,婴儿表情符号? (U 1F476),当不添加皮肤修饰剂时,会呈现中性黄色。相反,当肤色修改器跟随时,它会相应地发生变化。
? U 1F476
?? U 1F476 U 1F3FF
?? U 1F476 U 1F3FE
?? U 1F476 U 1F3FD
?? U 1F476 U 1F3FC
?? U 1F476 U 1F3FB

将表情符号连接在一起

表情符号/Unicode 标准最奇怪但可爱的决定是,一些表情符号是通过使用零宽度连接器将其他表情符号连接在一起而定义的,而不需要独立的代码点。

因此,例如,当我们组合时:
白旗?️ (U 1F3F3 U FE0F)
零宽度连接器 (U 200D)
彩虹 ? (U 1F308)

它显示为彩虹旗?️‍? (U 1F3F3 U FE0F U 200D U 1F308)

或者, ?? ? => ??‍?
甚至,?? ❤️? ?? => ??‍❤️‍?‍??

这就像将表情符号挤压在一起,然后,噗?,一个新的表情符号出现了。多可爱啊?


我想创建一个包含所有表情符号的 Markdown 表,而 Unicode 表情符号序列表是其真相来源。

https://unicode.org/Public/emoji/16.0/emoji-sequences.txt
https://unicode.org/Public/emoji/16.0/emoji-zwj-sequences.txt

因此,我创建了一个 Golang 解析器(此处),它获取并解析这些序列文件,在序列文件中描述范围时生成每个表情符号,并打印一个包含每个表情符号的一些内部信息的 Markdown 表(例如 零件(如果已加入),或基础 肤色等)。

您可以在这里找到降价表。

该表的最后一列的格式为:

Golang、Unicode 和 Rune


str := "⌚"
len([]rune(str)) // 1
len([]byte(str)) // 3


正如我们所讨论的,Golang 内部字符串编码是 UTF-8,这意味着,例如,对于时钟表情符号⌚,字节长度为 3(因为 UTF-8 生成 3 个字节来“写入”此代码点),码位长度为1。

Golang 符文 == Unicode 代码点

但是在连接表情符号的情况下 - 即使它“显示”为一个 - 我们有许多代码点(符文)甚至更多的字节。


str := "??‍❤️‍?‍??"
len([]rune(str)) // 10
len([]byte(str)) // 35


原因是:


??‍❤️‍?‍?? : ??   ZWJ   ❤️   ZWJ   ?   ZWJ   ??

??  : 1F469 1F3FC // ?   skin tone modifier [2 code points]
ZWJ : 200D // [1 code points] * 3
❤️  : 2764 FE0F // ❤   VS16 for emoji-style [2 code points]
?  : 1F48B // [1 code point]
??  : 1F468 1F3FE // ?   skin tone modifier [2 code points]



值得一提的是,我们如何看待表情符号取决于我们的系统字体以及该字体支持哪些版本的表情符号。

我不知道字体渲染的确切内部原理以及它如何正确渲染连接的字体。也许这将是一个未来的职位。

到那时,干杯吗?

版本聲明 本文轉載於:https://dev.to/moukoublen/unicode-emojis-and-a-bit-of-golang-3ced?1如有侵犯,請聯絡[email protected]刪除
最新教學 更多>
  • 解鎖 JavaScript 的隱藏寶石:未充分利用的功能可提高程式碼品質和效能
    解鎖 JavaScript 的隱藏寶石:未充分利用的功能可提高程式碼品質和效能
    In the ever-evolving landscape of web development, JavaScript remains a cornerstone technology powering countless large-scale web applications. While...
    程式設計 發佈於2024-11-07
  • 為什麼透過非常量指標修改「const」變數看起來有效,但實際上並沒有改變它的值?
    為什麼透過非常量指標修改「const」變數看起來有效,但實際上並沒有改變它的值?
    透過非常量指標修改 const在 C 中,const 變數一旦初始化就無法修改。但是,在某些情況下,const 變數可能會被更改。考慮以下代碼:const int e = 2; int* w = (int*)&e; // (1) *w = 5; ...
    程式設計 發佈於2024-11-07
  • Android - 將 .aab 檔案上傳到 Play 商店時出錯
    Android - 將 .aab 檔案上傳到 Play 商店時出錯
    如果您遇到此錯誤,請按照以下步驟操作以確保與您的套件名稱和簽署金鑰保持一致: 確保 app.json 檔案中的套件名稱與您第一次上傳 .aab 檔案時所使用的套件名稱相符。 "android": { "permissions":["CAMERA","READ_EXTERNAL_STO...
    程式設計 發佈於2024-11-07
  • 如何使用 PHP 將 HTML 轉換為 PDF
    如何使用 PHP 將 HTML 轉換為 PDF
    (適用於 Windows 的指南。不適用於 Mac 或 Linux) (圖片來源) 在 PHP 中將 HTML 轉換為 PDF 的方法不只一種。您可以使用Dompdf或Mpdf;但是,這兩個庫的執行方式有所不同。 注意:本文中並未包含所有解決方案。 要使用這兩個函式庫,您將需要 Composer...
    程式設計 發佈於2024-11-07
  • C++ 會擁抱垃圾收集嗎?
    C++ 會擁抱垃圾收集嗎?
    C 中的垃圾收集:實現和共識的問題C 中的垃圾收集:實現和共識的問題雖然有人建議C 最終會包含垃圾收集器,但它仍然是爭論和持續發展的主題。要理解其中的原因,我們必須深入研究迄今為止阻礙其納入的挑戰和考慮因素。 實現複雜性在 C 中加入隱式垃圾收集是一個非-瑣碎的任務。該語言的低級性質和對指針的廣泛支...
    程式設計 發佈於2024-11-07
  • 如何有條件地刪除 MySQL 中的欄位?
    如何有條件地刪除 MySQL 中的欄位?
    使用 MySQL ALTER 進行條件列刪除使用 MySQL ALTER 進行條件列刪除MySQL 中的 ALTER 指令提供了一種從表中刪除列的簡單方法。但是,當指定列不存在時,其傳統語法 (ALTER TABLE table_name DROP COLUMN column_name) 會引發錯誤...
    程式設計 發佈於2024-11-07
  • 你應該了解的現代 CSS 樣式 4
    你應該了解的現代 CSS 樣式 4
    TL;DR: 本博客使用代码示例来探索 Web 开发的五种最佳 CSS 样式和功能:容器查询、子网格、伪类、逻辑属性和实验室颜色空间。它们增强响应能力、简化布局并提高设计一致性。 层叠样式表 (CSS) 是一种众所周知的用于设计网页样式的语言。使用 CSS,您可以通过添加空格来自定义 HTML 元素...
    程式設計 發佈於2024-11-07
  • 箭頭函數或父作用域何時定義函數的參數?
    箭頭函數或父作用域何時定義函數的參數?
    ES6 箭頭函數中的參數:官方說明在 ES6 箭頭函數中,arguments 關鍵字的行為一直是爭論的話題。一些瀏覽器和平台(例如 Chrome、Firefox 和 Node)偏離了最初的 TC39 建議,引發了對該規範正確解釋的質疑。 根據官方 ES6 規範,箭頭函數沒有其自身的定義。自己的參數在...
    程式設計 發佈於2024-11-07
  • 根據您提供的內容,以下是一些採用問題格式的潛在文章標題:

* 載入資料本地內文件存取被拒絕:如何排除和修復錯誤? 
* 為什麼要載入資料LOCA
    根據您提供的內容,以下是一些採用問題格式的潛在文章標題: * 載入資料本地內文件存取被拒絕:如何排除和修復錯誤? * 為什麼要載入資料LOCA
    LOAD DATA LOCAL INFILE 存取被錯誤拒絕:不允許使用的命令當利用MySQL 的LOAD DATA INFILE 執行PHP 腳本時,它可能會遇到錯誤“用戶訪問被拒絕...(使用密碼:是)”。常見的解決方法是切換到 LOAD DATA LOCAL INFILE,儘管這可能會導致同一...
    程式設計 發佈於2024-11-07
  • 如何在 Python 中檢查文字檔是否為空?
    如何在 Python 中檢查文字檔是否為空?
    確定文字檔案是否為空在程式設計領域,通常需要確定特定檔案是否包含任何資料或無效。本文深入探討了這樣一個問題:「我們如何確定文字檔案是否為空?」Python 作為一種多功能程式語言,為這個問題提供了一個簡單的解決方案。透過利用 os.stat() 函數,我們可以檢索有關檔案的屬性數組,包括其大小。 查...
    程式設計 發佈於2024-11-07
  • 在 MySQL 中儲存 IPv6 位址的最佳方式是什麼?
    在 MySQL 中儲存 IPv6 位址的最佳方式是什麼?
    在MySQL 中儲存IPv6 位址:DECIMAL(39,0) 與VARBINARY(16)當面臨儲存IPv6 的挑戰時對於MySQL 中的位址,開發人員通常會考慮兩個選項:DECIMAL(39,0) 和2*BIGINT。雖然兩者各有優點,但出現了較以前的方法更具優勢的新解決方案。 DECIMAL(...
    程式設計 發佈於2024-11-07
  • ES6 類別是 JavaScript 原型模式的語法糖嗎?
    ES6 類別是 JavaScript 原型模式的語法糖嗎?
    ES6 類別只是 Javascript 中原型模式的語法糖嗎? 不,ES6 類別不僅僅是 Javascript 原型模式的語法糖原型模式。 雖然它們確實有一些相似之處,但也存在一些關鍵差異,這些差異使 ES6 類別成為創建和使用物件的更強大、更方便的方式。 以下是關鍵差異的細分ES6 類別與原型模...
    程式設計 發佈於2024-11-07
  • #daysofMiva 挑戰賽的第一天。
    #daysofMiva 挑戰賽的第一天。
    100 天挑戰的第一天 日期: 8/21/2024 目標: 學習並理解 JavaScript 中的變數、邏輯運算和資料類型,使用 JavaScript 解決數學問題,並開始學習事件監聽器和條件語句。 1. JavaScript變數介紹 今天,我透過學習變數開始了 JavaScrip...
    程式設計 發佈於2024-11-07
  • 如何將 PHP 產生的值安全地整合到 JavaScript 程式碼中?
    如何將 PHP 產生的值安全地整合到 JavaScript 程式碼中?
    將PHP 產生的值合併到頁面上的JavaScript 中嘗試將PHP 產生的值嵌入到JavaScript 程式碼中時,您可能會遇到類似於給定範例中的錯誤。要解決此問題,請考慮以下方法:<?php $htmlString = 'testing'; ?> <html> &l...
    程式設計 發佈於2024-11-07
  • 了解非同步 JavaScript
    了解非同步 JavaScript
    JavaScript 是一種單執行緒語言,這意味著它一次只能做一件事。然而,Web 應用程式通常需要執行從伺服器取得資料等任務,這可能需要一些時間。如果 JavaScript 必須等待每個任務完成才能繼續,那麼您的 Web 應用程式將會變得緩慢且無回應。這就是非同步(async)JavaScript...
    程式設計 發佈於2024-11-07

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3