Stream.Write 與 StreamWriter.Write 的不同
一、測(cè)試方法是否結(jié)果相同
首先看下面兩段代碼1是StreamWriter.Write 2是Stream.Write:
1
Stream ms = new MemoryStream();
string str = "這是測(cè)試字符串";
StreamWriter sw = new StreamWriter(ms, Encoding.UTF8);
sw.Write(str);
sw.Flush();
2
Stream ms = new MemoryStream();
string str = "這是測(cè)試字符串";
byte[] buffer = Encoding.UTF8.GetBytes(str);
ms.Write(buffer, 0, buffer.Length);
ms.Flush();
上面我們可以看到StreamWriter.Write的可讀性更好一些。
但是這兩段代碼執(zhí)行后的ms是否是相同的結(jié)果呢?
首先我們來(lái)看下長(zhǎng)度吧,在代碼最后分別加上
Console.WriteLine("StreamWriter.Write:{0}", ms.Length);
Console.WriteLine("Stream.Write:{0}", ms.Length);
執(zhí)行后結(jié)果如下:
各位看官,看到這里有何想法?
二、深究原因
下面繼續(xù)深究一下這個(gè)多出來(lái)的3個(gè)字節(jié)
在方法后面都加上如下一段代碼將MemoryStream的內(nèi)容以十六進(jìn)制的形式打印出來(lái)
ms.Position = 0;
byte[] bytes = new byte[ms.Length];
ms.Read(bytes, 0, bytes.Length);
foreach (var item in bytes){
Console.Write(item.ToString("X2") + " ");
}
Console.WriteLine(String.Empty);
再次執(zhí)行結(jié)果如下:
這里我們發(fā)現(xiàn)用StreamWriter.Write輸出多出了EF BB BF這3個(gè)字節(jié)
Google一下:多出來(lái)的這個(gè)玩意是 字節(jié)順序記號(hào)(英語(yǔ):byte-order mark,BOM)
在維基百科中可以查到:
編碼 | 表示 (十六進(jìn)制) | 表示 (十進(jìn)制) |
---|---|---|
UTF-8 | EF BB BF | 239 187 191 |
UTF-16(大端序) | FE FF | 254 255 |
UTF-16(小端序) | FF FE | 255 254 |
UTF-32(大端序) | 00 00 FE FF | 0 0 254 255 |
UTF-32(小端序) | FF FE 00 00 | 255 254 0 0 |
UTF-7 | 2B 2F 76和以下的一個(gè)字節(jié):[ 38 | 39 | 2B | 2F ] | 43 47 118和以下的一個(gè)字節(jié):[ 56 | 57 | 43 | 47 ] |
en:UTF-1 | F7 64 4C | 247 100 76 |
en:UTF-EBCDIC | DD 73 66 73 | 221 115 102 115 |
en:Standard Compression Scheme for Unicode | 0E FE FF | 14 254 255 |
en:BOCU-1 | FB EE 28 及可能跟隨著FF | 251 238 40 及可能跟隨著255 |
ok,了解了這個(gè)東西后我們就就需要知道在StreamWriter.Write中能否用代碼控制不輸出這個(gè)BOM嗎?
三、查找解決辦法
開(kāi)始反編譯StreamWriter.Write這個(gè)方法:
大致猜測(cè)是紅色方框的代碼輸出了BOM信息,ok再進(jìn)去看:
果然在這里,看上圖紅框處,GetPreamble方法是獲取編碼的字節(jié)序列,和我們之前查到的信息完全一致。
好下面繼續(xù)找這個(gè)haveWrittenPreamble有沒(méi)設(shè)置的可能,在Init方法中找到了它的身影。
杯具了,CanSeed沒(méi)有set方法,Write之前的Position肯定為0,至此結(jié)束。
四、結(jié)論
由上面的結(jié)論,我們可以確定:
1.如果雙方協(xié)議無(wú)BOM時(shí),可以使用Stream.Write方法來(lái)輸出,或者使用StreamWriter.Write時(shí)加入new UTF8Encoding(false)參數(shù)。
2.有BOM時(shí),我們可以通過(guò)GetPreamble和Stream.Write來(lái)完成StreamWriter.Write的功能。
相關(guān)文章
C#操作Windows服務(wù)類(lèi)System.ServiceProcess.ServiceBase
這篇文章介紹了C#操作Windows服務(wù)類(lèi)System.ServiceProcess.ServiceBase,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-05-05C# 獲取當(dāng)前月份天數(shù)的三種方法總結(jié)
本篇文章主要是對(duì)C#中獲取目前月份的天數(shù)的三種方法進(jìn)行了詳細(xì)的總結(jié)介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2014-01-01Unity實(shí)現(xiàn)游戲傷害數(shù)字顯示HUD的方法
游戲中收到傷害掉血,會(huì)有飄動(dòng)的傷害數(shù)值,本文主要介紹Unity實(shí)現(xiàn)游戲傷害數(shù)字顯示HUD的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10C#中Winfrom默認(rèn)輸入法的設(shè)置方法
這篇文章主要介紹了C#中Winfrom默認(rèn)輸入法的設(shè)置方法,以實(shí)例形式較為詳細(xì)的分析了C#中輸入法設(shè)置的相關(guān)技巧,需要的朋友可以參考下2015-05-05