所以我使用大小为1024的缓冲区(byte [])通过套接字接收数据,并且我希望在它们大于1024字节的情况下将读取组合在一起形成整个数据包。我选择了一个List来存储整个数据包,我想要做的是添加每个缓冲区读取它。我想做:
List.AddRange(Buffer);
但是如果缓冲区未满,则会将一堆空字节填充到最后。所以我自然想要做的只是在List中添加一定范围的字节,但是没有这样的方法。我总是可以创建一个完全接收的字节数的临时字节数组,然后使用AddRange()并得到我想要的结果,但这对我来说似乎很愚蠢。更不用说它会创建然后在每次读取数据时丢弃一个数组,这对可伸缩多用户服务器上的性能不利。
有没有办法用List做到这一点?或者我可以使用其他一些数据结构吗?
答案 0 :(得分:6)
如果您使用的是C#3.5(LINQ)
list.AddRange(buffer.Take(count));
答案 1 :(得分:2)
你实际上需要结果是List<byte>
吗?之后你打算用它做什么?如果你真的只需要一个IEnumerable<byte>
我建议创建这样的东西:
using System;
using System.Collections;
using System.Collections.Generic;
public class ArraySegmentConcatenator<T> : IEnumerable<T>
{
private readonly List<ArraySegment<T>> segments =
new List<ArraySegment<T>>();
public IEnumerator<T> GetEnumerator()
{
foreach (ArraySegment<T> segment in segments)
{
for (int i=0; i < segment.Count; i++)
{
yield return segment.Array[i+segment.Offset];
}
}
}
public void Add(ArraySegment<T> segment)
{
segments.Add(segment);
}
public void Add(T[] array)
{
segments.Add(new ArraySegment<T>(array));
}
public void Add(T[] array, int count)
{
segments.Add(new ArraySegment<T>(array, 0, count));
}
public void Add(T[] array, int offset, int count)
{
segments.Add(new ArraySegment<T>(array, offset, count));
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
然后您可以每次添加相关的细分。当然,你最终可能会浪费大量的内存,而且每次都要小心创建一个新的缓冲区(而不是再次阅读原文),但在其他方面它会很有效。
答案 2 :(得分:1)
对于.Net3.5,您可以使用.Take()
扩展方法仅返回您收到的实际字节数。
答案 3 :(得分:0)
我不知道您正在使用什么协议,或者您是否正在实现自定义协议,但如果您确定了大小,则可以使用Buffer.BlockCopy
直接将字节复制到新数组以添加到您的列表。
当你没有具体细节时,很难更简洁。
答案 4 :(得分:0)
您可以实现自己的IEnumerable实现,该实现仅从数组中检索您想要的字节。然后你可以这样做:
List.AddRange(new BufferEnumerator(Buffer));
您还可以查看:
new System.ArraySegment(Buffer,0,numBytesRecieved)
如果ArraySegment可行,我不肯定我记得读过它的一些缺点但不记得细节。
答案 5 :(得分:0)
您可以使用Array.Copy()并仅使用数组来构建目标缓冲区:
byte[] recvBuffer = new byte[1024];
byte[] message = new byte[0];
int nReaded;
while ((nReaded = ....Read(recvBuffer, 1024) > 0)
{
byte[] tmp = new byte[message.Length + nReaded];
Buffer.BlockCopy(message, 0, tmp, 0, message.Length);
Buffer.BlockCopy(recvBuffer, 0, tmp, message.Length, nReaded);
message = tmp;
}
编辑:使用与Quintin Robinson在评论中建议的Buffer.BlockCopy()替换Array.Copy()。