Unicode 字符串轉 UTF-8 編碼算法剖析

📊 Unicode 字符串轉 UTF-8 編碼算法剖析

——從 C# char 到 C++ wchar_t 的編碼轉換原理

引用:UTF-8 編解碼可視化分析


🔍 1. 算法功能概述

該函數將 Unicode 字符串(C# string)轉換為 UTF-8 編碼的字節數組,同時輸出有效字節數 count
核心流程

  1. 計算 UTF-8 編碼所需字節數
  2. 分配緩沖區(額外預留 3 字節)
  3. 逐字符編碼為 UTF-8 字節序列
開始
計算字節數
分配緩沖區
編碼轉換
返回結果

🧠 2. 算法原理與 UTF-8 編碼規則

UTF-8 是變長編碼,規則如下:

在這里插入圖片描述

Unicode 碼點范圍UTF-8 字節序列結構字節數位模式圖示
U+0000 ~ U+007F0xxxxxxx1[0xxx xxxx]
U+0080 ~ U+07FF110xxxxx 10xxxxxx2[110x xxxx] [10xx xxxx]
U+0800 ~ U+FFFF1110xxxx 10xxxxxx 10xxxxxx3[1110 xxxx] [10xx xxxx] [10xx xxxx]

💡 :C# char 為 16 位 Unicode,C++ wchar_t 在 Windows 中與之等價(Linux 為 32 位)。


🔄 3. 算法流程詳解
步驟 1:計算 UTF-8 字節數

在這里插入圖片描述

int k = 0;
while (i < s.Length) {char ch = s[i++];if (ch < 0x80) k++;        // ASCII 字符(1 字節)else if (ch < 0x800) k += 2; // 2 字節字符else if (ch < 0x10000) k += 3; // 3 字節字符(含 CJK 字符)
}
count = k; // 輸出有效字節數
  • 時間復雜度:O(n),需遍歷整個字符串。
步驟 2:分配緩沖區
buf = new byte[count + 3]; // 額外分配 3 字節(安全填充)
  • 為什么 +3?
    預留空間防止溢出(UTF-8 單字符最多占 3 字節),確保寫入安全。
步驟 3:編碼轉換(核心)

在這里插入圖片描述

fixed (byte* p = buf) { // 固定內存地址(避免 GC 移動)while (i < s.Length) {char ch = s[i++];// 1 字節編碼(ASCII)if (ch < 0x80) p[k++] = (byte)(ch & 0xFF); // 2 字節編碼(拉丁字母擴展)else if (ch < 0x800) {p[k++] = (byte)(((ch >> 6) & 0x1F) | 0xC0); // 110xxxxxp[k++] = (byte)((ch & 0x3F) | 0x80);        // 10xxxxxx}// 3 字節編碼(中/日/韓文字符)else if (ch < 0x10000) {p[k++] = (byte)(((ch >> 12) & 0x0F) | 0xE0); // 1110xxxxp[k++] = (byte)(((ch >> 6) & 0x3F) | 0x80); // 10xxxxxxp[k++] = (byte)((ch & 0x3F) | 0x80);         // 10xxxxxx}}
}
  • 位操作解析
    原始字符
    位分解
    添加前綴
    組合字節

?? 4. 算法局限性
算法局限
不支持代理對
緩沖區浪費
缺少4字節編碼
無法處理表情符號
多分配3字節
不支持補充平面
  • 不支持代理對(Surrogate Pairs)
    無法處理 U+10000 以上的字符(如 emoji 𠮷),需補充 4 字節編碼邏輯。
  • 緩沖區浪費:多分配 3 字節(可通過精確計算優化)。

📝 5. 完整代碼(含逐行注釋)
public static byte[] GetUTF8StringBuffer(string s, out int count)
{count = 0; // 初始化輸出參數if (s == null){throw new ArgumentNullException("s"); // 空字符串檢查}byte[] buf = null; // 存儲結果的字節數組int k = 0;         // 臨時計數器(字節數/寫入位置)int i = 0;         // 字符串遍歷索引// === 步驟 1:計算 UTF-8 編碼所需字節數 ===while (i < s.Length){char ch = s[i++]; // 逐個讀取字符if (ch < 0x80)    // ASCII 字符(0x00 ~ 0x7F){k++;          // 占 1 字節}else if (ch < 0x800) // 0x80 ~ 0x7FF(拉丁字母擴展){k += 2;       // 占 2 字節}else if (ch < 0x10000) // 0x800 ~ 0xFFFF(CJK 字符等){k += 3;       // 占 3 字節}}// === 步驟 2:分配緩沖區(額外 +3 字節) ===buf = new byte[(count = k) + 3]; // count 賦值為 k,總長度 = k+3// === 步驟 3:編碼轉換(不安全代碼塊) ===unsafe // 啟用不安全代碼{fixed (byte* p = buf) // 固定緩沖區內存地址{i = 0; // 重置字符串索引k = 0; // 重置字節數組索引while (i < s.Length){char ch = s[i++]; // 讀取下一個字符// --- 1 字節編碼 ---if (ch < 0x80){p[k++] = (byte)(ch & 0xFF); // 直接存儲低 8 位}// --- 2 字節編碼 ---else if (ch < 0x800){// 構造首字節:110xxxxx (0xC0 | 高 5 位)p[k++] = (byte)(((ch >> 6) & 0x1F) | 0xC0);// 構造次字節:10xxxxxx (0x80 | 低 6 位)p[k++] = (byte)((ch & 0x3F) | 0x80);}// --- 3 字節編碼 ---else if (ch < 0x10000){// 構造首字節:1110xxxx (0xE0 | 高 4 位)p[k++] = (byte)(((ch >> 12) & 0x0F) | 0xE0);// 構造次字節:10xxxxxx (0x80 | 中 6 位)p[k++] = (byte)(((ch >> 6) & 0x3F) | 0x80);// 構造尾字節:10xxxxxx (0x80 | 低 6 位)p[k++] = (byte)((ch & 0x3F) | 0x80);}}}}return buf; // 返回 UTF-8 字節數組
}

🎯 6. 總結
算法價值
高效編碼轉換
跨語言兼容
內存安全
優化方向
支持4字節編碼
精確緩沖區分配
使用Span提升性能
  • 核心價值:高效實現 Unicode 到 UTF-8 的轉換,適用于網絡傳輸或跨語言交互。
  • 優化方向
    1. 支持 4 字節編碼(代理對)
    2. 移除多余緩沖區分配
    3. 使用 Span<byte> 提升性能

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/93939.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/93939.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/93939.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

php的安全性到底怎么樣

PHP作為一種流行的服務器端腳本語言&#xff0c;被廣泛應用于Web開發。然而&#xff0c;由于PHP是一種較為靈活的語言&#xff0c;其安全性議題一直備受爭議。在這篇文章中&#xff0c;我將從多個方面來討論PHP的安全性&#xff0c;包括常見的安全漏洞、防范措施以及最佳實踐。…

mapbox高階,結合threejs(threebox)添加建筑glb模型,添加陰影效果,設置陰影顏色和透明度

????? 主頁: gis分享者 ????? 感謝各位大佬 點贊?? 收藏? 留言?? 加關注?! ????? 收錄于專欄:mapbox 從入門到精通 文章目錄 一、??前言 1.1 ??mapboxgl.Map 地圖對象 1.2 ??mapboxgl.Map style屬性 1.3 ??threebox loadObj加載模型 二、??…

SSM從入門到實戰:1.6 Spring數據訪問與JDBC模板

&#x1f44b; 大家好&#xff0c;我是 阿問學長&#xff01;專注于分享優質開源項目解析、畢業設計項目指導支持、幼小初高的教輔資料推薦等&#xff0c;歡迎關注交流&#xff01;&#x1f680; 06-Spring數據訪問與JDBC模板 &#x1f4d6; 本文概述 本文是SSM框架系列Spri…

下一代IT服務管理:ITIL5會是什么樣?

ITIL4發布到現在也就5年多時間&#xff0c;按照以往的更新節奏&#xff0c;ITIL5最早也得2027年之后。但現在IT發展的速度&#xff0c;跟以前完全不是一個量級。AI都快把我們的飯碗搶了&#xff08;開個玩笑&#xff09;&#xff0c;ITIL要是還按部就班&#xff0c;估計真要被時…

最新研究進展:2023-2025年神經機器翻譯突破性成果

文章目錄 一、模型架構創新 1.1 混合架構的崛起 1.2 多模態翻譯的突破 1.3 大語言模型與NMT的深度融合(2023-2024) 1.4 非自回歸翻譯(NAT)的效率革命(2024) 二、數據與訓練策略優化 2.1 低資源語言翻譯的飛躍 2.2 動態數據增強技術 三、效率與部署 3.1 模型壓縮與加速 3.…

OpenTelemetry WebSocket 監控終極方案:打通最后一公里

概述 OpenTelemetry&#xff0c;以下簡稱 OTEL&#xff0c;是由 CNCF 托管的“一站式可觀測性標準”&#xff0c;把指標、鏈路、日志三大信號統一為單一 SDK/API&#xff0c;零侵入地采集從瀏覽器、移動端到后端、容器、云服務的全棧遙測數據&#xff0c;并支持 40 后端一鍵導…

VS Code 出現的 Web 視圖加載錯誤和服務工作者注冊失敗問題解決方案

針對 VS Code 或 Cursor &#xff08;vscode系&#xff09;中出現的 Web 視圖加載錯誤和服務工作者注冊失敗問題&#xff0c;以下是永久性解決方案的完整操作指南&#xff1a;解決方案步驟打開命令面板 使用快捷鍵 CtrlShiftP&#xff08;Windows/Linux&#xff09;或 CmdShift…

【qml-4】qml與c++交互(類型多例)

背景&#xff1a; 【qml-1】qml與c交互第一次嘗試&#xff08;實例注入&#xff09; 【qml-2】嘗試一個有模式的qml彈窗 【qml-3】qml與c交互第二次嘗試&#xff08;類型注冊&#xff09; 【qml-4】qml與c交互&#xff08;類型多例&#xff09; 【qml-5】qml與c交互&#…

圖數據庫如何構筑 Web3 風控防線 聚焦批量注冊與鏈上盜轉 悅數圖數據庫

隨著 Web3 生態的不斷演進&#xff0c;鏈上風險呈現出團伙化、隱蔽化和動態化的趨勢&#xff0c;傳統的單點風控手段已難以應對復雜多變的攻擊模式。尤其在批量注冊薅羊毛與鏈上交易盜轉洗錢等高頻風險場景中&#xff0c;攻擊者往往通過偽造身份、跨鏈操作、多層嵌套轉賬等方式…

恒流源電路學習

恒流源的設計原理&#xff1a; 如圖所示你可以看到右邊的的推到公式得到紅點處的電壓是一個和左邊相關的定值&#xff0c;所以呢右邊的電流就是電壓除以那個4Ω&#xff0c;所以得到右邊的電路的電流大體是一個定值&#xff0c;不管你再加什么東西都可以保持這個電流&#xff…

基于生成對抗網絡的模糊圖像恢復原理與技術實現

1. 引言圖像模糊是數字圖像處理中的常見問題&#xff0c;其成因包括相機抖動、物體運動、聚焦不良等。傳統方法如維納濾波、Lucy-Richardson 算法等依賴于模糊核估計和逆濾波&#xff0c;在復雜場景下性能有限。生成對抗網絡&#xff08;Generative Adversarial Networks, GAN&…

【Doris 系列】Doris IP 變更修復

FE 恢復 異常日志 查看 fe.out 會有以下報錯&#xff0c;此時 fe 進程是無法啟動的&#xff0c;操作前注意備份所有 fe 的元數據并停止上游讀寫動作&#xff01; java.io.IOException: the self host 192.168.31.78 does not equal to the host in ROLE file 192.168.31.81. Yo…

安卓14系統應用收不到開機廣播

安卓14系統應用收不到開機廣播 - Wesley’s Blog 前段時間有測試反饋在安卓14 上面某系統應用恢復出廠設置后沒有自啟動&#xff0c;究竟是什么原因呢&#xff1f; 回顧 Android 從3.1開始&#xff0c;會將新安裝并且從未被啟動的應用置為“STOPPED”狀態&#xff0c;或者被…

C# Attribute 方法擴展

場景 剛寫完一個干凈利落的方法&#xff0c;比如保存數據到數據庫&#xff0c;邏輯清晰、結構優雅&#xff0c; 第二天&#xff0c;“嘿&#xff0c;保存完數據&#xff0c;記得給客戶發個郵件哦~” 第三天&#xff0c;“能不能再發個消息通知其他系統&#xff1f;” 第四天&am…

【URP】[法線貼圖]為什么主要是藍色的?

【從UnityURP開始探索游戲渲染】專欄-直達 法線貼圖呈現藍紫色調&#xff08;尤其以藍色為主&#xff09;是由其?存儲原理、切線空間坐標系設計及顏色編碼規則共同決定的?。 核心原因&#xff1a;法線向量的存儲規則? ?法線向量的物理范圍? 法線是單位向量&#xff0c;…

驅動開發系列63 - NVIDIA 開源GPU驅動open-gpu-kernel-modules編譯調試

目錄 一:通過apt方式安裝nvidia 驅動 二:通過 .run 方式安裝nvidia驅動 三:編譯安裝nvidia開源內核驅動 四:驗證和調試 五:卸載驅動 1. 以apt方式安裝nvidia 驅動的卸載方法 2. 以.run方式安裝nvidia驅動的卸載方法 六:安裝CUDA環境 一:通過apt方式安裝nvidia 驅動…

對KingbaseES架構的解析:從讀寫分離到異地災備的技術實現與保障機制

聲明&#xff1a;文章為本人真實測評博客&#xff0c;非廣告&#xff0c;并沒有推廣該平臺 &#xff0c;為用戶體驗文章 本人旨在分享最真實的用戶體驗&#xff0c;為關注此類產品的朋友們提供一個客觀的參考。 文章目錄一、架構全景&#xff1a;四級高可用構建數字基礎1.1 物…

Visual Studio中的常用調試功能(上)

1、利用斷點進行調試添加斷點的方式有以下幾種1.鍵盤快捷鍵F92.通過菜單【Debug&#xff08;調試&#xff09;】-》【Toggle BreakPoint&#xff08;切換斷點&#xff09;】3.點擊代碼行左邊的空白處&#xff08;推薦&#xff09;設置斷點后&#xff0c;按F5運行程序&#xff0…

Linux -- 線程同步

1.1條件變量 (1)當?個線程互斥地訪問某個變量時&#xff0c;它可能發現在其它線程改變狀態之前&#xff0c;它什么也做不了。 (2)例如?個線程訪問隊列時&#xff0c;發現隊列為空&#xff0c;它只能等待&#xff0c;只到其它線程將?個節點添加到隊列 中。這種情況就需要?到…

前端進階指南:JavaScript性能優化實戰全解析

深入剖析 JavaScript 性能瓶頸&#xff0c;分享優化技巧與最佳實踐&#xff0c;讓你的前端應用更快、更穩、更流暢。 &#x1f4d1; 目錄 一、前言 二、性能瓶頸的常見來源 三、JavaScript代碼優化技巧 1. 避免重復計算 2. 合理使用防抖與節流 3. 使用事件委托 四、渲染…