首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 程式設計總結(九):字元編碼基礎與亂碼成因分析

     編輯:關於C#

前言

亂碼是開發者常遇到的痛點。本文從字元、字元集、字元編碼的基本概念切入,詳細比較 ASCII、GB2312、GBK、Big5、GB18030、Unicode、UTF-8 等常見編碼的特點與差異,並透過實際程式碼示範不同編碼間轉換的結果,幫助徹底理解亂碼產生的根本原因。

核心概念

  • 字元:電腦中使用的字母、數字、符號總稱。
  • 字元集:系統支援的所有抽象字元集合。
  • 字元編碼:建立自然語言符號與機器可識別數值(位元組序列)的對應規則。

常見編碼詳解

1. ASCII 編碼

單位元組編碼,僅包含 128 個字符(擴展後 256 個),僅支援英文字母、數字及基本符號,無法表示中文等非英文字符。

2. 中文編碼體系

  • GB2312:簡體中文國家標準,雙位元組編碼,收錄 6763 個漢字,覆蓋 99.75% 使用頻率。
  • GBK:微軟擴展 GB2312,收錄 GB 13000.1-93 全部字符,支援繁體、日韓漢字等,共 21003 個字符。
  • Big5:繁體中文通用標準,雙位元組編碼,收錄 13060 個漢字,流行於台灣、香港、澳門。
  • GB18030:中國最新國家標準,與 GB2312 兼容、與 GBK 基本兼容,支援 Unicode 所有統一漢字,收錄 70244 個漢字。

3. Unicode 與 UTF-8

Unicode 為全球統一字元集,每個符號擁有唯一碼位,固定 4 位元組儲存(UTF-32),空間浪費大。
UTF-8 是 Unicode 的變長實現方式:英文字母 1 位元組,常用漢字 3 位元組,極少用字 4 位元組,節省空間且相容 ASCII,成為網路傳輸主流。

UTF-8 編碼規則:
1) 單位元組符號:最高位 0,後 7 位為 Unicode 碼。
2) n 位元組符號 (n>1):第一位元組前 n 位為 1,第 n+1 位為 0,後續位元組前兩位皆為 10,剩餘位填 Unicode 碼。

為什麼會出現亂碼?

不同編碼間無法完全相容。例如以 UTF-8 編碼的資料若以 GB2312 解碼,位元組序列對應錯誤字符,產生亂碼。好比雙方說不同語言,強行對話自然無法理解。

實戰演示:多編碼轉換對比

以下程式碼展示同一組字串(英文、簡體、繁體)在 ASCII、GB2312、Big5、Unicode、UTF-8 等編碼下的位元組表示與轉換結果:

using System;
using System.Text;

namespace EncodingSample {
    class Program {
        static void Main(string[] args) {
            string str_en = "Welcome to the Encoding world.";
            string str_cn = "歡迎來到編碼世界!";
            string str_tw = "歡迎來到編碼世界";
            Encoding defaultEncoding = Encoding.Default;
            Console.WriteLine("預設編碼:{0}", defaultEncoding.BodyName);

            TestEncoding(Encoding.ASCII, "ASCII", defaultEncoding, str_en, str_cn, str_tw);
            TestEncoding(Encoding.GetEncoding("GB2312"), "GB2312", defaultEncoding, str_en, str_cn, str_tw);
            TestEncoding(Encoding.GetEncoding("BIG5"), "BIG5", defaultEncoding, str_en, str_cn, str_tw);
            TestEncoding(Encoding.Unicode, "Unicode", defaultEncoding, str_en, str_cn, str_tw);
            TestEncoding(Encoding.UTF8, "UTF8", defaultEncoding, str_en, str_cn, str_tw);
            Console.ReadKey();
        }

        static void TestEncoding(Encoding dstEncoding, string name, Encoding srcEncoding, params string[] strs) {
            Console.WriteLine("----{0}編碼----", name);
            foreach (var s in strs) {
                OutputByEncoding(srcEncoding, dstEncoding, s);
            }
            Console.WriteLine("------------------------------------");
        }

        static void OutputByEncoding(Encoding src, Encoding dst, string srcStr) {
            byte[] srcBytes = src.GetBytes(srcStr);
            Console.WriteLine("原始位元組: {0}", BitConverter.ToString(srcBytes));
            byte[] dstBytes = Encoding.Convert(src, dst, srcBytes);
            Console.WriteLine("目標位元組: {0}", BitConverter.ToString(dstBytes));
            string result = dst.GetString(dstBytes);
            Console.WriteLine("解碼結果: {0}", result);
        }
    }
}

ASCII 碼表 ASCII 擴展表 執行結果 1 執行結果 2

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved