使用二进制流(即byte[]
数组)时,使用BinaryReader
或BinaryWriter
的要点似乎是简化从流中读取/写入原始数据类型,使用ReadBoolean()
等方法并考虑编码。这是整个故事吗?如果直接使用Stream
,而不使用BinaryReader/BinaryWriter
,是否存在固有的优势或劣势?大多数方法,例如Read()
,在两个类中似乎都是相同的,我的猜测是它们在下面工作相同。
考虑一个以两种不同方式处理二进制文件的简单示例(编辑:我意识到这种方式无效,可以使用缓冲区,它只是一个示例):
// Using FileStream directly
using (FileStream stream = new FileStream("file.dat", FileMode.Open))
{
// Read bytes from stream and interpret them as ints
int value = 0;
while ((value = stream.ReadByte()) != -1)
{
Console.WriteLine(value);
}
}
// Using BinaryReader
using (BinaryReader reader = new BinaryReader(FileStream fs = new FileStream("file.dat", FileMode.Open)))
{
// Read bytes and interpret them as ints
byte value = 0;
while (reader.BaseStream.Position < reader.BaseStream.Length)
{
value = reader.ReadByte();
Console.WriteLine(Convert.ToInt32(value));
}
}
输出将是相同的,但内部发生了什么(例如从OS的角度来看)?是 - 一般来说 - 重要的是使用哪种实现?如果您不需要他们提供的额外方法,是否有使用BinaryReader/BinaryWriter
的目的?
对于这种特定情况,MSDN就Stream.ReadByte()
:
Stream上的默认实现创建了一个新的单字节数组 然后调用Read。虽然这是正式的,但确实如此 低效的。
使用GC.GetTotalMemory()
,第一种方法似乎分配的空间是第二种方法的2倍,但如果使用更通用的Stream.Read()
方法,AFAIK就不应该这样(例如使用缓冲区读取块。不过,在我看来,这些方法/接口可以轻松统一......
答案 0 :(得分:14)
不,两种方法之间没有本质区别。额外的Reader增加了一些缓冲,所以你不应该混合它们。但是,不要期望任何重大的性能差异,它们都由实际的I / O支配。
所以,
byte[]
移动时使用流。在许多流媒体场景中很常见。 byte
)数据时,请使用BinaryWriter和BinaryReader。它们的主要目的是将内置框架类型转换为byte[]
。 答案 1 :(得分:10)
一个很大的区别是如何缓冲I / O.如果您在此处或那里只编写/读取几个字节,BinaryWriter/BinaryReader
将运行良好。但是如果你必须读取数据的MB,那么一次读取一个byte
,Int32
等等将会有点慢。你可以改为阅读更大的块并从那里解析。
示例:
// Using FileStream directly with a buffer
using (FileStream stream = new FileStream("file.dat", FileMode.Open))
{
// Read bytes from stream and interpret them as ints
byte[] buffer = new byte[1024];
int count;
// Read from the IO stream fewer times.
while((count = stream.Read(buffer, 0, buffer.Length)) > 0)
for(int i=0; i<count; i++)
Console.WriteLine(Convert.ToInt32(buffer[i]));
}
现在这有点偏离主题......但我会把它扔出去:
如果你想变得非常狡猾...并且真的给自己一个性能提升......(虽然,它可能被认为是危险的)而不是解析每个Int32
,你可以使用{{1一次性完成所有这些操作}}
另一个例子:
Buffer.BlockCopy()
关于这个例子需要注意几点:这个每个Int32需要4个字节而不是一个...所以它会产生不同的结果。您也可以为Int32以外的其他数据类型执行此操作,但许多人会认为编组应该在您的脑海中。 (我只是想提出一些值得考虑的事情......)
答案 2 :(得分:0)
两个代码都执行相同的操作,即。 ReadByte(),它以字节数组结尾,因此两种方法的结果相同(来自同一文件)。
OS的实现(内部差异)是流被缓存在虚拟内存中,例如。如果您是通过流在网络上传输文件,则仍将剩余系统内存用于其他(多)任务。
对于字节数组,整个文件在传输到磁盘(文件创建)或其他流之前将存储在内存中,因此不建议用于大文件。
这里有一些关于通过网络传输二进制数据的讨论:
When to use byte array, and when to use stream?
@Jason C和@Jon Skeet在这里提出了一个要点:
Why do most serializers use a stream instead of a byte array?
我注意到,当我继续使用Win 10机器(4 GB RAM)通过System.Net.Http.Httpclient
GetByteArrayAsync
方法(与GetStreamAsync
)传输文件时,有时会跳过5MB以上的文件,而无需等待传输完成。
PS:.Net 4.0字节数组限于2GB