是否可以控制byte[]
数组中的索引位置?在下面的代码中,我期望value1
的返回值进入join
的前七个字节,value2
的返回值依次进入8 9 10 11位置。但这不会发生。前七个字节丢失,因为索引始终位于0位置。如何控制指数位置?
static void Main(string[] args)
{
byte[] join = new byte[15];
join = value1(); //seven byte enters.
join = value2(); //next four byte enters.
// 'join' should now have eleven bytes.
string a = Encoding.UTF8.GetString(join);
Console.WriteLine(a);
Console.ReadLine();
}
public static byte[] value1()
{
string first = "welcome";
byte[] f = Encoding.UTF8.GetBytes(first);
return f;// seven byte returning.
}
public static byte[] value2()
{
string second = "home";
byte[] s = Encoding.UTF8.GetBytes(second);
return s;//four byte returning.
}
我知道可以使用Array.Copy()
或Buffer.BlockCopy()
重新组织代码。但是,如果代码运行100,000次或更多,这两种方法都很耗时。我期待避免这两种方法并直接在join
内获取返回值。
---由于
答案 0 :(得分:4)
有办法做你想做的事,但你必须要小心。这个GetBytes overload允许您指定要复制字节的字节数组,以及复制它们的索引。所以,在你的例子中,它看起来像这样:
byte[] join = new byte[15];
int ix = 0;
ix = ix + Encoding.UTF8.GetBytes(first, 0, first.Length, join, ix);
ix = ix + Encoding.UTF8.GetBytes(second, 0, second.Length, join, ix);
string a = Encoding.UTF8.GetString(join, 0, ix);
此处的ix
变量会跟踪编码的总字节数。
这里必须要小心在join
数组中分配足够的字节,并且必须跟踪编码的字节数,因为UTF-8(以及许多其他编码)可能需要单个字符多个字节。
您还希望看到GetString overload,它允许您指定数组中的起始位置和字节数。
如果要编写像value1
和value2
方法那样执行此操作的方法,则必须将字节数组和数组索引传递给方法。这些方法必须返回它们编码的字节数,否则它们必须将该值添加到索引并返回新索引。
答案 1 :(得分:3)
不是分配数组的项目,而是丢弃new byte[15]
并将其分配给新数组。您可以先尝试使用List<byte>
,然后将其转换为数组:
var byteList = new List<byte>(15);
byteList.AddRange(value1());
byteList.AddRange(value2());
byte[] join = byteList.ToArray();
另一种方法是为您的数组创建一个扩展方法,如下所示:
public static void SetItems<T>(this T[] source, int startIndex, IEnumerable<T> items)
{
// I omitted the checks (index, length, null etc.) but you should add them
int i = startIndex;
foreach(var item in items)
source[i++] = item;
}
然后叫它:
byte[] join = new byte[15];
join.SetItems(0, value1());
join.SetItems(4, value2());
这应该比第一个选项更快,因为它没有创建列表,但它要求您知道startIndex
,在这种情况下它不应该是一个问题..
答案 2 :(得分:3)
value1
和value2
方法返回字节数组,而您可能希望将值附加到现有的join
数组。
您可以使用Array.Copy
(或Buffer.BlockCopy
)将返回的值放在join
数组中:
var v1 = value1(); //seven byte returned.
var v2 = value2(); //next four byte returned.
var join = new byte[v1.Length + v2.Length];
// copy v1 at index 0 of join
Array.Copy(v1, 0, join, 0, v1.Length);
// copy v2 at index v1.Length of join
Array.Copy(v2, 0, join, v1.Length, v2.Length);
编辑:
我做了一个小基准来测试所提方法的性能,这是结果(每种方法有6百万次重复):
Benchmark results (6000000 repetitions) :
JoinCodeUsingArrayCopy : 4076021 ticks (1304 ms)
JoinCodeUsingSetItems : 4873634 ticks (1559 ms)
JoinCodeUsingList : 8729925 ticks (2793 ms)
JoinCodeUsingBufferBlockCopy : 3665075 ticks (1172 ms)
基准代码here。
正如您所看到的,Array.Copy/Buffer.BlockCopy
是最快的方法,即使使用列表的方法速度也不是很慢(我们谈论的是600万次迭代后差异的1.5秒)。
可能我会选择list方法,因为它是最干净的,因为它不需要直接使用偏移/起始索引。