1. 程式人生 > >.NET(C#):字元編碼(Encoding)和位元組順序標記(BOM)

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

什麼是字元順序標記(BOM)

計算機內部資料儲存都是二進位制的,只有知道一段資料的二進位制儲存格式,這段資料才有意義。所謂的文字檔案其實就是用一種特定的字元編碼來將二進位制源資料轉換成文字。多數文字編輯器都可以編輯不同編碼的文字檔案,那麼文字編輯器是怎樣通過源二進位制資料來得知這段資料的文字編碼呢?答案就是靠字元順序標記(Byte Order Mark),在文章裡面我們就統一用英文簡寫BOM指這一名詞。

下面是常用Unicode編碼的BOM

UTF-8: EF BB BF
UTF-16 big endian: FE FF
UTF-16 little endian: FF FE
UTF-32 big endian: 00 00 FE FF
UTF-32 little endian: FF FE 00 00

返回目錄

.NET中的Encoding類和BOM

在.NET的世界裡,我們經常用Encoding的靜態屬性來得到一個Encoding類,從這裡得到的編碼預設都是提供BOM的(如果支援BOM的話)。

如果你想讓指定編碼不提供BOM,那麼需要手動構造這個編碼類。

//不提供BOM的Encoding編碼
Encoding utf8NoBom =newUTF8Encoding(false);
Encoding utf16NoBom =newUnicodeEncoding(false, false);
Encoding utf32NoBom =newUTF32Encoding
(false, false);

另外這裡都是構造Little-endian的,Big-endian建構函式裡也有引數。

其次UnicodeEncoding類代表UTF16編碼。

Encoding類中的GetPreamble方法可以返回當前編碼提供的BOM,如下程式碼:

publicstaticvoid Main()
{
Encoding utf32WithBom =Encoding.UTF32;
Encoding utf32NoBom =newUTF32Encoding(false, false);

Console.WriteLine("UTF32 With BOM"
); PrintBytes(utf32WithBom.GetPreamble()); Console.WriteLine("UTF32 No Bom"); PrintBytes(utf32NoBom.GetPreamble()); } staticvoid PrintBytes(byte[] bytes) { if (bytes ==null|| bytes.Length ==0) Console.WriteLine("<無值>"); foreach (var b in bytes) Console.Write("{0:X2} ", b); Console.WriteLine(); }

輸出:

UTF32 With BOM
FF FE 00 00
UTF32 No Bom
<無值>
返回目錄

檔案讀寫和BOM

文字寫入時,StreamWriter類和File.WriteAllText方法的預設編碼都是不帶BOM的UTF8。

當然我們可以通過建構函式來指定一個其他編碼,構造方法就像上面講的一樣。比如:

publicstaticvoid Main()
{
Encoding utf32bigbom =newUTF32Encoding(true, true);
Encoding utf32litbom =newUTF32Encoding(false, true);
Encoding utf32litnobom =newUTF32Encoding(false, false);

var content ="abcde";
    WriteAndPrint(content, utf32bigbom);
    WriteAndPrint(content, utf32litbom);
    WriteAndPrint(content, utf32litnobom);
}

staticvoid WriteAndPrint(string content, Encoding enc)
{
var path =Path.GetTempFileName();
File.WriteAllText(path, content, enc);
    PrintBytes(File.ReadAllBytes(path));
}

staticvoid PrintBytes(byte[] bytes)
{
if (bytes ==null|| bytes.Length ==0)
Console.WriteLine("<無值>");
foreach (var b in bytes)
Console.Write("{0:X2} ", b);
Console.WriteLine();
}

輸出:

00 00 FE FF 00 00 00 61 00 00 00 62 00 00 00 63 00 00 00 64 00 00 00 65
FF FE 00 00 61 00 00 00 62 00 00 00 63 00 00 00 64 00 00 00 65 00 00 00
61 00 00 00 62 00 00 00 63 00 00 00 64 00 00 00 65 00 00 00

可以看出來:00 00 FE FF是UTF32 Big-endian的BOM,而FF FE 00 00是UTF32 Little-endian的BOM,第三行是沒有加BOM的UTF32的源二進位制資料。

讀文字的時候,當構造StringReader類進指定字串路徑或者Stream物件的話,StringReader的表現是自動通過BOM來判定字元編碼,當然我們也可以手動指定一個編碼(尤其是沒有BOM的文字資料,不手動指定編碼是無法正確讀取文字檔案的)。

同樣,File類的ReadAllText也具備同樣功能,不過,細心地讀者可能發現Reflector中File.ReadAllText的原始碼是用UTF8編碼的StreamReader讀取檔案的,其實它呼叫了StreamReader中的這個建構函式:

public StreamReader(string path, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize)
{   /* 內容省略*/  }

那麼雖然傳入的一個特定的編碼,但這個detectEncodingFromByteOrderMarks引數是true的,StreamReader還是會自動覺察BOM來讀檔案的。

程式碼:

publicstaticvoid Main()
{
var path1 =Path.GetTempFileName();
var
            
           

相關推薦

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

什麼是字元順序標記(BOM) 計算機內部資料儲存都是二進位制的,只有知道一段資料的二進位制儲存格式,這段資料才有意義。所謂的文字檔案其實就是用一種特定的字元編碼來將二進位制源資料轉換成文字。多數文字編輯器都可以編輯不同編碼的文字檔案,那麼文字編輯器是怎樣通過源二

轉-NET(C#)線程本地存儲(Thread-Local Storage)之ThreadStatic, LocalDataStoreSlotThreadLocal<T>

輸出 修改 pla star 目錄 div .net 4.0 current cor NET(C#):線程本地存儲(Thread-Local Storage)之ThreadStatic, LocalDataStoreSlot和ThreadLocal<T>

PHP介面字元編碼資料格式由請求方定義

根據一個老專案寫介面,發現專案檔案編碼為gbk,而且資料庫也是gbk,由於程式碼量巨大,不可能更改專案程式碼以及資料庫的字元編碼。 請求介面的也有好多個: 老客戶一直用的gbk字元編碼的資料來請求的,原來寫的介面收到的資料格式為xml, 新客戶要求用utf-8格式,接收資料為json。 看了

Python3_字元編碼EncodingASCII,Unicode,UTF-8

Python 3的字串str型別用Unicode,直接支援多語言。 當str和bytes互相轉換時,需要指定編碼。最常用的編碼是UTF-8。Python當然也支援其他編碼方式,比如把Unicode編碼成GB2312: >>> '中文'.encode('gb2312') b'

.NET(C#)警惕PLINQ結果的無序性

inf wrap title tle arch c# 定性 並發執行 分割 .NET(C#):警惕PLINQ結果的無序性 2012年08月10日 ⁄ 綜合 ⁄ 共 620字 ⁄ 字號 小 中 大 ⁄ 評論關閉

.NET(C#)XML序列化時派生類的處理

ali main 基類 bsp 處理 program ext serial pub .NET(C#):XML序列化時派生類的處理 針對基類的XmlSerializer序列化派生類 第一種方法是在基類添加XmlInclude特性,這樣的話基類的XmlSerializer可以

C++虛函數多態

變量 bsp ++ 多態 直接 構造函數 沒有 相同 派生類 C++中虛函數的唯一用處就是構成多態。 C++提供多態的目的是:可以通過基類指針對所有派生類(包括直接派生和間接派生)的成員變量和成員函數進行“全方位”的訪問,尤其是成員函數。如果沒有多態,我們只能訪問成員變量。

C++探索std::mapstd::unordered_map中的新增操作

std::map和std::unordered_map主要提供如下幾種新增操作: try_emplace ()   (C++17) emplace () insert() [] = 下面給出一段測試程式碼,觀察物件在新增到std::map中時,

C++ extern關鍵字功能用法研究

今天遇到在aaa.cpp檔案中定義如下函式:                                   &nbs

Java之路字元編碼

計算機裡只有數字,計算機軟體裡的一切都是用數字來表示,螢幕上顯示的一個個字元也不例外。 最開始計算機是在美國使用,當時所用到的字元也就是現在鍵盤上的一些符號和少數幾個特殊的符號,每一個字元都用一個數字來表示,一個位元組所能表示的數字範圍內(0~255)足以容納所有的字元,實

C++探索std::mapstd::unordered_map中最高效的新增操作

std::map和std::unordered_map主要提供如下幾種新增操作: try_emplace ()   (C++17) emplace () insert() 下面給出一段測試程式碼,觀察物件在新增到std::map中時,構造物件過程中會有什麼區別: #i

Java IO4字元編碼

前言       字元編碼,這本不屬於IO的內容,但位元組流之後寫的應該是字元流,既然是字元流,那就涉及一個"字元編碼的"問題,考慮到字元編碼不僅僅是在IO這塊,Java中很多場景都涉及到這個概念,因此這邊文章就專門詳細寫一下字元編碼,具體的網上有很多,但

有關於【該檔案的字元編碼需要在傳輸協議層宣告,或者在檔案中加入一個 BOM位元組順序標記)】的另一種解決辦法

昨天測試一個介面的時候發現一個異常,瀏覽器訪問一個controller,然後帶了一個JSON格式的引數,然後瀏覽器返回400錯誤,除錯發現下面的錯誤資訊: 純文字檔案的字元編碼未宣告。如果該檔案包含 US-ASCII 範圍之外的字元,該檔案將在某些瀏覽器配置中呈現為亂碼。該

【垂直搜尋引擎搭建11】使用htmlparser獲取頁面的字元編碼encoding

1,確定目標。對於html頁面來說,一般都有確定編碼的語句: <meta http-equiv=”Content-Type” content=”text/html; charset=gb2312″ /> 可以通過這一行的特徵來取出網頁的編碼。

C++中文編碼轉換

在介紹如何使用C++11標準庫進行中文編碼轉換之前,先說說一下byte string、multibyte string、wide string之間的區別。 byte string 由8位元的位元組組成的字串。由char表示位元組。因而字串長度=位元組數=char數 m

廖雪峰老師Python學習(2)字元編碼

字元編碼 我們已經講過了,字串也是一種資料型別,但是,字串比較特殊的是還有一個編碼問題。 因為計算機只能處理數字,如果要處理文字,就必須先把文字轉換為數字才能處理。最早的計算機在設計時採用8個位元(bit)作為一個位元組(byte),所以,一個位元組能表示的最大的整數就是255(二進位制11

JAVA初窺字元編碼

參考書籍:《深入分析Java Web技術內幕(修訂版)》----許令波著 編碼問題一直在困擾著程式開發人員,這在Java中尤其突出,因為Java是跨平臺語言,字元在不同平臺之間進行傳輸時經常需要進行編碼切換。 為什麼要編碼? 眾所周知,計算機其實是很笨的,它只識別數字0和

Python字元編碼詳解

相關文章 1. 字元編碼簡介 1.1. ASCII ASCII(American Standard Code for Information Interchange),是一種單位元組的編碼。計算機世界裡一開始只有英文,而單位元組可以表示256個不同的字元,可以表示所有的英文字元和許多的控制符號。不過

字元編碼ANSIASCII區別、UnicodeUTF-8區別

今天看了一個說法,說是入坑windows程式開發,必先掌握文字的編碼和字符集知識。本部落格就整理下資訊儲存和字元編碼的相關知識。 一.位: 計算機儲存資訊的最小單位,稱之為位(bit),音譯位元,二進位制的一個“0”或一個“1”叫一位。 二.位元組 位元

Python筆記字元編碼unicode/utf-8

請尊重原創作品。轉載請保持文章完整性,並以超連結形式註明原始作者“tingsking18”和主站點地址,方便其他朋友提問和指正。 Unicode和Python的中文處理   在Python語言中,Uincode字串處理一直是一個容易讓人迷惑的問題。許多Python