是否有一种优雅的方法来模拟该StreamReader.ReadToEnd
方法BinaryReader
?也许将所有字节放入一个字节数组中?
我这样做:
read1.ReadBytes((int)read1.BaseStream.Length);
...但必须有更好的方法。
是否有一种优雅的方法来模拟该StreamReader.ReadToEnd
方法BinaryReader
?也许将所有字节放入一个字节数组中?
我这样做:
read1.ReadBytes((int)read1.BaseStream.Length);
...但必须有更好的方法。
只需这样做:
byte[] allData = read1.ReadBytes(int.MaxValue);
文档说它将读取所有字节,直到到达流的末尾。
尽管这看起来很优雅,并且文档似乎表明这会起作用,但实际实现(在 .NET 2、3.5 和 4 中检查)为数据分配了一个完整大小的字节数组,这可能会导致OutOfMemoryException
32位系统。
因此,我会说实际上没有一种优雅的方式。
相反,我会推荐@iano 答案的以下变体。此变体不依赖 .NET 4:为(或者,代码都相同)
创建扩展方法。BinaryReader
Stream
public static byte[] ReadAllBytes(this BinaryReader reader)
{
const int bufferSize = 4096;
using (var ms = new MemoryStream())
{
byte[] buffer = new byte[bufferSize];
int count;
while ((count = reader.Read(buffer, 0, buffer.Length)) != 0)
ms.Write(buffer, 0, count);
return ms.ToArray();
}
}
使用 BinaryReader没有简单的方法可以做到这一点。如果您不知道需要提前读取的计数,更好的选择是使用 MemoryStream:
public byte[] ReadAllBytes(Stream stream)
{
using (var ms = new MemoryStream())
{
stream.CopyTo(ms);
return ms.ToArray();
}
}
为了避免调用时的额外副本ToArray()
,您可以改为Position
通过GetBuffer()
.
要将流的内容复制到另一个,我已经解决了读取“一些”字节的问题,直到到达文件末尾:
private const int READ_BUFFER_SIZE = 1024;
using (BinaryReader reader = new BinaryReader(responseStream))
{
using (BinaryWriter writer = new BinaryWriter(File.Open(localPath, FileMode.Create)))
{
int byteRead = 0;
do
{
byte[] buffer = reader.ReadBytes(READ_BUFFER_SIZE);
byteRead = buffer.Length;
writer.Write(buffer);
byteTransfered += byteRead;
} while (byteRead == READ_BUFFER_SIZE);
}
}
解决此问题的另一种方法是使用 C# 扩展方法:
public static class StreamHelpers
{
public static byte[] ReadAllBytes(this BinaryReader reader)
{
// Pre .Net version 4.0
const int bufferSize = 4096;
using (var ms = new MemoryStream())
{
byte[] buffer = new byte[bufferSize];
int count;
while ((count = reader.Read(buffer, 0, buffer.Length)) != 0)
ms.Write(buffer, 0, count);
return ms.ToArray();
}
// .Net 4.0 or Newer
using (var ms = new MemoryStream())
{
stream.CopyTo(ms);
return ms.ToArray();
}
}
}
使用这种方法将允许可重用和可读的代码。
我使用它,它利用底层BaseStream
属性为您提供所需的长度信息。它使事情变得简单而美好。
以下是三种扩展方法BinaryReader
:
Range
类型来指定您感兴趣的数据子集。public static class BinaryReaderExtensions {
public static byte[] ReadBytesToEnd(this BinaryReader binaryReader) {
var length = binaryReader.BaseStream.Length - binaryReader.BaseStream.Position;
return binaryReader.ReadBytes((int)length);
}
public static byte[] ReadAllBytes(this BinaryReader binaryReader) {
binaryReader.BaseStream.Position = 0;
return binaryReader.ReadBytes((int)binaryReader.BaseStream.Length);
}
public static byte[] ReadBytes(this BinaryReader binaryReader, Range range) {
var (offset, length) = range.GetOffsetAndLength((int)binaryReader.BaseStream.Length);
binaryReader.BaseStream.Position = offset;
return binaryReader.ReadBytes(length);
}
}
然后使用它们变得微不足道和清晰......
// 1 - Reads everything in as a byte array
var rawBytes = myBinaryReader.ReadAllBytes();
// 2 - Reads a string, then reads the remaining data as a byte array
var someString = myBinaryReader.ReadString();
var rawBytes = myBinaryReader.ReadBytesToEnd();
// 3 - Uses a range to read the last 44 bytes
var rawBytes = myBinaryReader.ReadBytes(^44..);
有同样的问题。
首先,使用 FileInfo.Length 获取文件的大小。
接下来,创建一个字节数组并将其值设置为 BinaryReader.ReadBytes(FileInfo.Length)。例如
var size = new FileInfo(yourImagePath).Length;
byte[] allBytes = yourReader.ReadBytes(System.Convert.ToInt32(size));