字串 (Unicode UTF-16) 與位元組陣列 (各種編碼) 之間的轉換**必須透過 Encoding**,無無參數建構函式,使用靜態屬性取得預設編碼實例。
| 屬性 | 編碼 | 用途 |
| Encoding.UTF8 | UTF-8 (無 BOM) | **現代首選**,網頁、API、檔案、跨平台 |
| Encoding.Unicode | UTF-16 LE (含 BOM) | Windows 內部、.NET 字串原生格式 |
| Encoding.BigEndianUnicode | UTF-16 BE | 網路協定、特定檔案格式 |
| Encoding.ASCII | US-ASCII (0-127) | 僅英數符號,非 ASCII 字元會變 '?' |
| Encoding.Default | 系統當前 ANSI 代碼頁 | **舊版相容**,繁中=Big5,簡中=GB2312,**不可攜帶** |
| Encoding.GetEncoding("big5") | Big5 (繁體中文) | 繁中舊系統/檔案 |
| Encoding.GetEncoding("gb2312") | GB2312 (簡體中文) | 簡中舊系統/檔案 |
字串 → 位元組陣列
string text = "C# 程式設計";
byte[] utf8 = Encoding.UTF8.GetBytes(text); // 最常用
byte[] big5 = Encoding.GetEncoding("big5").GetBytes(text);
byte[] unicode = Encoding.Unicode.GetBytes(text); // 含 BOM: FF FE
// 手動加入/移除 BOM
byte[] utf8WithBom = Encoding.UTF8.GetPreamble().Concat(utf8).ToArray();
byte[] utf8NoBom = utf8.Skip(Encoding.UTF8.GetPreamble().Length).ToArray(); // 若已含 BOM
位元組陣列 → 字串
byte[] data = { 0x48, 0x65, 0x6C, 0x6C, 0x6F }; // "Hello" in ASCII/UTF-8
string s = Encoding.UTF8.GetString(data); // "Hello"
// 部分解碼
string part = Encoding.UTF8.GetString(data, 1, 3); // "ell"
// 串流式解碼 (大資料)
using var ms = new MemoryStream(data);
using var sr = new StreamReader(ms, Encoding.UTF8);
string all = sr.ReadToEnd();
編碼差異實測
string s = "C#語言";
byte[] ansi = Encoding.Default.GetBytes(s); // 視系統而定 (Big5/GB2312)
byte[] utf8 = Encoding.UTF8.GetBytes(s);
byte[] unicode = Encoding.Unicode.GetBytes(s);
Console.WriteLine($"Default: {ansi.Length} bytes - {BitConverter.ToString(ansi)}");
// Big5: 6 bytes - 43-23-D3-D7-B8-AE
Console.WriteLine($"UTF8: {utf8.Length} bytes - {BitConverter.ToString(utf8)}");
// UTF8: 8 bytes - 43-23-E8-AA-9E-E8-A8-80
Console.WriteLine($"Unicode: {unicode.Length} bytes - {BitConverter.ToString(unicode)}");
// Unicode: 10 bytes - FF-FE-43-00-23-00-35-8A-57-8A (含 BOM)
最佳實踐
- 新專案統一 UTF-8:
Encoding.UTF8 (無 BOM),跨平台、無亂碼、標準化。
- 讀取舊檔案:嘗試 UTF-8 → 失敗嘗試 Big5/GB2312,或要求使用者指定編碼。
- 指定編碼寫入檔案:
File.WriteAllText(path, text, Encoding.UTF8) (預設 UTF-8 無 BOM)。
- 網路協定/序列化:協定規範通常指定 UTF-8 或 Binary 格式 (Protobuf, MessagePack),勿假設預設編碼。
- 避免 Encoding.Default:不同機器/區域設定結果不同,導致不可重現 Bug。
效能提示
- 重複使用
Encoding 實例 (靜態屬性已為單例)。
- 大量轉換使用
Encoder/Decoder 串流式 API (GetEncoder()/GetDecoder()) 避免中間陣列配置。
Span<byte> / Span<char> 配合 Encoding.GetBytes/GetChars 多載實現零複製切片轉換 (.NET Core 3.1+)。
掌握 Encoding 運作機制與編碼選擇原則,即能徹底解決中文亂碼與跨平台相容問題。
- 上一篇文章: C# 字串與字元陣列雙向轉換完整指南
- 下一篇文章: C# GZipStream 壓縮解壓縮陷阱:必須 Close 才能正確讀取
Copyright ©
程式碼之家 All Rights Reserved