搜尋
首頁後端開發C#.Net教程關於.NET(C#)正確讀取中文編碼檔案的實例教程

首先如果讀者對編碼或BOM還不熟悉的話,推薦先讀這篇文章:.NET(C#):字元編碼(Encoding)和位元組順序標記(BOM)。
中文編碼基本上可以分成兩大類:
1. ANSI編碼的擴充集合:例如GBK, GB2312, GB18030等,這類編碼都不存在BOM(一些更新的標準中文編碼,例如GB18030和GBK編碼,都向後相容GB2312編碼)。
2. Unicode編碼集合:如UTF-8, UTF-16, UTF-32等。這類編碼可以有BOM,也可以不加BOM。
3. 部分Unicode編碼還存在具體字節次序問題(Endianess),就是所謂的Little endian和Big endian之分,不同此節次序對於不同的BOM,比如UTF16,不過UTF8不存在字節次序問題。

OK,了解了基本知識後,讓我們回到主題,該如何正確開啟中文文字檔案。第一個需要確認的訊息是:你的Unicode編碼檔案是否包含BOM?

如果包含BOM的話,那麼一切好說!因為如果我們發現了BOM,我們就知道他的具體編碼了。如果沒有發現BOM,那就不是Unicode,我們用系統預設的ANSI擴充中文編碼集打開文字檔就OK了。
而如果Unicode編碼沒有BOM的話(顯然,你不能保證用戶給你的所有Unicode檔案都是有BOM的),那麼你要手動從原始位元組中判斷他是GBK?還是UTF8?還是其他編碼? 。這就需要具體的編碼覺察演算法了(可以google “charset|encoding detection”), 當然編碼覺察演算法不一定會100%準確,正是因為這點,Windows記事本會有Bush hid the facts bug。在Chrome瀏覽網頁時,也會遇到亂碼的狀況的。個人感覺,Notepad++的編碼覺察做的還是很準確的。
編碼覺察演算法很多,例如這個工程:https://code.google.com/p/ude

 
如果Unicode都帶BOM的話,則不需要第三方類別庫了。不過也有一些需要說明的地方。

問題就是.NET中讀取文字方法(File類別和StreamReader)預設是以UTF8編碼來讀取的,因此此類GBK的文字檔案直接用.NET開啟(不指定編碼的話)結果肯定是亂碼!

首先這裡最有效地解決方案是使用系統預設的ANSI擴展編碼,也就是系統預設的非Unicode編碼來讀取文本,參考代碼:

//输出系统默认非Unicode编码Console.WriteLine(Encoding.Default.EncodingName);//使用系统默认非Unicode编码来打开文件var fileContent = File.ReadAllText("C:\test.txt", Encoding.Default);

在簡體中文的Windows系統下應該輸出:

簡體中文(GB2312)...

而且使用這個方法其實是不限於簡體中文的。

當然也可以手動去指定一個編碼,例如就是GBK編碼,但是如果用指定的GBK編碼去打開一個Unicode文件,文件還會打開成功嗎?答案是仍然成功。原因是.NET在開啟文件時預設會自動覺察BOM然後用根據BOM得到的編碼去開啟文件,如果沒有BOM再用使用者指定的編碼區開啟文件,如果使用者沒有指定編碼,則使用UTF8編碼。

這個」自動覺察BOM「的參數可以在StreamReader中建構函式中設置,對應detectEncodingFromByteOrderMarks參數。

但是在File類別的對應方法中無法設定。 (例如:File.ReadAllText)。

例如下面程式碼,分別用:

GB2312編碼,自動覺察BOM 來讀取GB2312文字

GB2312編碼,自動覺察BOM 來讀取Unicode文字

GB2312編碼,不覺察BOM 來讀取Unicode文字

static void Main(){    var gb2312 = Encoding.GetEncoding("GB2312");    //用GB2312编码,自动觉察BOM 来读取GB2312文本    ReadFile("gbk.txt", gb2312, true);    //用GB2312编码,自动觉察BOM 来读取Unicode文本    ReadFile("unicode.txt", gb2312, true);    //用GB2312编码,不觉察BOM 来读取Unicode文本    ReadFile("unicode.txt", gb2312, false);}//通过StreamReader读取文本 static void ReadFile(string path, Encoding enc, bool detectEncodingFromByteOrderMarks){    StreamReader sr;    using (sr = new StreamReader(path, enc, detectEncodingFromByteOrderMarks))    {        Console.WriteLine(sr.ReadToEnd());    }}

輸出:

a刘a刘???

第三行是亂碼。

看到上面,使用GB2312編碼去開啟Unicode檔案也會成功的。因為「自動覺察BOM」參數為True,所以當發現該文件有BOM,.NET會透過BOM覺察到是Unicode文件,然後用Unicode去開啟文件的。當然如果沒有BOM,會使用指定的編碼參數去開啟檔案。對於GB2312編碼的文本,顯然是沒有BOM的,所以必須指定GB2312編碼,否則.NET會用預設的UTF8編碼去解析文件,是無法讀取結果的。第三行出現亂碼則是由於「自動覺察BOM」為False,.NET會直接用指定的GB2312編碼去讀取一個有BOM的Unicode編碼文字文件,顯然無法成功的。

當然還可以自己判斷BOM,如果沒有BOM的話,指定一個預設編碼去開啟文字。我在以前一篇文章中寫過(.NET(C#):從文件中覺察編碼)。

代碼:

static void Main(){    PrintText("gb2312.txt");    PrintText("unicode.txt");}//根据文件自动觉察编码并输出内容static void PrintText(string path){    var enc = GetEncoding(path, Encoding.GetEncoding("GB2312"));    using (var sr = new StreamReader(path, enc))    {        Console.WriteLine(sr.ReadToEnd());    }}/// <summary>/// 根据文件尝试返回字符编码/// </summary>/// <param name="file">文件路径</param>/// <param name="defEnc">没有BOM返回的默认编码</param>/// <returns>如果文件无法读取,返回null。否则,返回根据BOM判断的编码或者缺省编码(没有BOM)。</returns>static Encoding GetEncoding(string file, Encoding defEnc){    using (var stream = File.OpenRead(file))    {        //判断流可读?        if (!stream.CanRead)            return null;        //字节数组存储BOM        var bom = new byte[4];        //实际读入的长度        int readc;        readc = stream.Read(bom, 0, 4);        if (readc >= 2)        {            if (readc >= 4)            {                //UTF32,Big-Endian                if (CheckBytes(bom, 4, 0x00, 0x00, 0xFE, 0xFF))                    return new UTF32Encoding(true, true);                //UTF32,Little-Endian                if (CheckBytes(bom, 4, 0xFF, 0xFE, 0x00, 0x00))                    return new UTF32Encoding(false, true);            }            //UTF8            if (readc >= 3 && CheckBytes(bom, 3, 0xEF, 0xBB, 0xBF))                return new UTF8Encoding(true);            //UTF16,Big-Endian            if (CheckBytes(bom, 2, 0xFE, 0xFF))                return new UnicodeEncoding(true, true);            //UTF16,Little-Endian            if (CheckBytes(bom, 2, 0xFF, 0xFE))                return new UnicodeEncoding(false, true);        }        return defEnc;    }}//辅助函数,判断字节中的值static bool CheckBytes(byte[] bytes, int count, params int[] values){    for (int i = 0; i < count; i++)        if (bytes[i] != values[i])            return false;    return true;}

上面程式碼,對於Unicode文本,GetEncoding方法會傳回UTF16編碼(更具體:還會根據BOM傳回Big或Little-Endian的UTF16編碼),而沒有BOM的檔案則會傳回預設值GB2312編碼。

Related Posts:

.NET(C#):從檔案中覺察編碼

.NET(C#):字元編碼(Encoding)和位元組順序標記(BOM )

.NET(C#):使用System.Text.Decoder類別來處理「流程文字」

.NET(C#):淺談組件清單資源與RESX資源

以上是關於.NET(C#)正確讀取中文編碼檔案的實例教程的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
如何使用C#编写时间序列预测算法如何使用C#编写时间序列预测算法Sep 19, 2023 pm 02:33 PM

如何使用C#编写时间序列预测算法时间序列预测是一种通过分析过去的数据来预测未来数据趋势的方法。它在很多领域,如金融、销售和天气预报中有广泛的应用。在本文中,我们将介绍如何使用C#编写时间序列预测算法,并附上具体的代码示例。数据准备在进行时间序列预测之前,首先需要准备好数据。一般来说,时间序列数据应该具有足够的长度,并且是按照时间顺序排列的。你可以从数据库或者

如何使用Redis和C#开发分布式事务功能如何使用Redis和C#开发分布式事务功能Sep 21, 2023 pm 02:55 PM

如何使用Redis和C#开发分布式事务功能引言分布式系统的开发中,事务处理是一项非常重要的功能。事务处理能够保证在分布式系统中的一系列操作要么全部成功,要么全部回滚。Redis是一种高性能的键值存储数据库,而C#是一种广泛应用于开发分布式系统的编程语言。本文将介绍如何使用Redis和C#来实现分布式事务功能,并提供具体代码示例。I.Redis事务Redis

如何实现C#中的人脸识别算法如何实现C#中的人脸识别算法Sep 19, 2023 am 08:57 AM

如何实现C#中的人脸识别算法人脸识别算法是计算机视觉领域中的一个重要研究方向,它可以用于识别和验证人脸,广泛应用于安全监控、人脸支付、人脸解锁等领域。在本文中,我们将介绍如何使用C#来实现人脸识别算法,并提供具体的代码示例。实现人脸识别算法的第一步是获取图像数据。在C#中,我们可以使用EmguCV库(OpenCV的C#封装)来处理图像。首先,我们需要在项目

Redis在C#开发中的应用:如何实现高效的缓存更新Redis在C#开发中的应用:如何实现高效的缓存更新Jul 30, 2023 am 09:46 AM

Redis在C#开发中的应用:如何实现高效的缓存更新引言:在Web开发中,缓存是提高系统性能的常用手段之一。而Redis作为一款高性能的Key-Value存储系统,能够提供快速的缓存操作,为我们的应用带来了不少便利。本文将介绍如何在C#开发中使用Redis,实现高效的缓存更新。Redis的安装与配置在开始之前,我们需要先安装Redis并进行相应的配置。你可以

如何使用C#编写动态规划算法如何使用C#编写动态规划算法Sep 20, 2023 pm 04:03 PM

如何使用C#编写动态规划算法摘要:动态规划是求解最优化问题的一种常用算法,适用于多种场景。本文将介绍如何使用C#编写动态规划算法,并提供具体的代码示例。一、什么是动态规划算法动态规划(DynamicProgramming,简称DP)是一种用来求解具有重叠子问题和最优子结构性质的问题的算法思想。动态规划将问题分解成若干个子问题来求解,通过记录每个子问题的解,

分享几个.NET开源的AI和LLM相关项目框架分享几个.NET开源的AI和LLM相关项目框架May 06, 2024 pm 04:43 PM

当今人工智能(AI)技术的发展如火如荼,它们在各个领域都展现出了巨大的潜力和影响力。今天大姚给大家分享4个.NET开源的AI模型LLM相关的项目框架,希望能为大家提供一些参考。https://github.com/YSGStudyHards/DotNetGuide/blob/main/docs/DotNet/DotNetProjectPicks.mdSemanticKernelSemanticKernel是一种开源的软件开发工具包(SDK),旨在将大型语言模型(LLM)如OpenAI、Azure

C#的就业前景如何C#的就业前景如何Oct 19, 2023 am 11:02 AM

无论您是初学者还是有经验的专业人士,掌握C#将为您的职业发展铺平道路。

如何实现C#中的图像压缩算法如何实现C#中的图像压缩算法Sep 19, 2023 pm 02:12 PM

如何实现C#中的图像压缩算法摘要:图像压缩是图像处理领域中的一个重要研究方向,本文将介绍在C#中实现图像压缩的算法,并给出相应的代码示例。引言:随着数字图像的广泛应用,图像压缩成为了图像处理中的重要环节。压缩能够减小存储空间和传输带宽,并能提高图像处理的效率。在C#语言中,我们可以通过使用各种图像压缩算法来实现对图像的压缩。本文将介绍两种常见的图像压缩算法:

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
2 週前By尊渡假赌尊渡假赌尊渡假赌
倉庫:如何復興隊友
4 週前By尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒險:如何獲得巨型種子
4 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)