我正在尝试将字节流拆分为越来越大的块。
源流包含未知数量的字节,读取成本很高。枚举器的输出应该是大小不断增加的字节数组,从8KB开始到1MB。
这非常简单,只需读取整个流,将其存储在数组中,然后取出相关部分。然而,由于流可能非常大,因此立即读取它是不可行的。此外,虽然性能不是主要问题,但保持系统负载非常低是很重要的。
在实现这一点时,我注意到保持代码的简短性和可维护性相对困难。还有一些与流相关的问题需要记住(例如,即使成功,stream.Read也可能无法填充缓冲区)。
我没有找到任何现有的类来帮助我的案例,也没有在网上找到类似的东西。你将如何实现这样一个类?
public IEnumerable<BufferWrapper> getBytes(Stream stream)
{
List<int> bufferSizes = new List<int>() { 8192, 65536, 220160, 1048576 };
int count = 0;
int bufferSizePostion = 0;
byte[] buffer = new byte[bufferSizes[0]];
bool done = false;
while (!done)
{
BufferWrapper nextResult = new BufferWrapper();
nextResult.bytesRead = stream.Read(buffer, 0, buffer.Length);
nextResult.buffer = buffer;
done = nextResult.bytesRead == 0;
if (!done)
{
yield return nextResult;
count++;
if (count > 10 && bufferSizePostion < bufferSizes.Count)
{
count = 0;
bufferSizePostion++;
buffer = new byte[bufferSizes[bufferSizePostion]];
}
}
}
}
public class BufferWrapper
{
public byte[] buffer { get; set; }
public int bytesRead { get; set; }
}
显然,何时增加缓冲区大小以及如何选择缓冲区大小的逻辑可能会改变。
有些人可能还可以找到一种更好的方法来处理最后一个要发送的缓冲区,因为这不是最有效的方法。
作为参考,我目前使用的实现,已经根据@Servy 的回答进行了改进
private const int InitialBlockSize = 8 * 1024;
private const int MaximumBlockSize = 1024 * 1024;
private Stream _Stream;
private int _Size = InitialBlockSize;
public byte[] Current
{
get;
private set;
}
public bool MoveNext ()
{
if (_Size < 0) {
return false;
}
var buf = new byte[_Size];
int count = 0;
while (count < _Size) {
int read = _Stream.Read (buf, count, _Size - count);
if (read == 0) {
break;
}
count += read;
}
if (count == _Size) {
Current = buf;
if (_Size <= MaximumBlockSize / 2) {
_Size *= 2;
}
}
else {
Current = new byte[count];
Array.Copy (buf, Current, count);
_Size = -1;
}
return true;
}