Stream.Write 与 StreamWriter.Write 的不同



Stream.Write 与 StreamWriter.Write 是我们在向流中写数据时,最常用的方法。下面就详细讲解这两个方法。


一、测试方法是否结果相同
首先看下面两段代码1是StreamWriter.Write 2是Stream.Write:



1代码如下:


Stream ms = new MemoryStream();
string str = "这是测试字符串";
StreamWriter sw = new StreamWriter(ms, Encoding.UTF8);
sw.Write(str);
sw.Flush();


2 代码如下:

Stream ms = new MemoryStream();
string str = "这是测试字符串";
byte[] buffer = Encoding.UTF8.GetBytes(str); 
ms.Write(buffer, 0, buffer.Length);
ms.Flush();


上面我们可以看到StreamWriter.Write的可读性更好一些。

但是这两段代码执行后的ms是否是相同的结果呢?

首先我们来看下长度吧,在代码最后分别加上


代码如下:


Console.WriteLine("StreamWriter.Write:{0}", ms.Length);
Console.WriteLine("Stream.Write:{0}", ms.Length);


执行后结果如下:



各位看官,看到这里有何想法?


二、深究原因
下面继续深究一下这个多出来的3个字节


在方法后面都加上如下一段代码将MemoryStream的内容以十六进制的形式打印出来


代码如下:


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);


再次执行结果如下:


这里我们发现用StreamWriter.Write输出多出了EF BB BF这3个字节

Google一下:多出来的这个玩意是 字节顺序记号(英语:byte-order mark,BOM)

在维基百科中可以查到:


编码表示 (十六进制)表示 (十进制)
UTF-8EF BB BF239 187 191
UTF-16(大端序)FE FF254 255
UTF-16(小端序)FF FE255 254
UTF-32(大端序)00 00 FE FF0 0 254 255
UTF-32(小端序)FF FE 00 00255 254 0 0
UTF-72B 2F 76和以下的一个字节:[ 38 | 39 | 2B | 2F ]43 47 118和以下的一个字节:[ 56 | 57 | 43 | 47 ]
en:UTF-1F7 64 4C247 100 76
en:UTF-EBCDICDD 73 66 73221 115 102 115
en:Standard Compression Scheme for Unicode0E FE FF14 254 255
en:BOCU-1FB EE 28 及可能跟随着FF251 238 40 及可能跟随着255


ok,了解了这个东西后我们就就需要知道在StreamWriter.Write中能否用代码控制不输出这个BOM吗?


三、查找解决办法
开始反编译StreamWriter.Write这个方法:


大致猜测是红色方框的代码输出了BOM信息,ok再进去看:


 



果然在这里,看上图红框处,GetPreamble方法是获取编码的字节序列,和我们之前查到的信息完全一致。


好下面继续找这个haveWrittenPreamble有没设置的可能,在Init方法中找到了它的身影。


 



杯具了,CanSeed没有set方法,Write之前的Position肯定为0,至此结束。


四、结论
由上面的结论,我们可以确定:


1.如果双方协议无BOM时,可以使用Stream.Write方法来输出,或者使用StreamWriter.Write时加入new UTF8Encoding(false)参数。


2.有BOM时,我们可以通过GetPreamble和Stream.Write来完成StreamWriter.Write的功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值