将字节数组转换为一定长度的数组段

时间:2018-09-08 05:30:24

标签: c# arrays loops split byte

我有一个字节数组,我想返回一定大小的连续块(​​以新字节数组的形式)。

我尝试过:

originalArray = BYTE_ARRAY
var segment = new ArraySegment<byte>(originalArray,0,640); 
byte[] newArray = new byte[640];
for (int i = segment.Offset; i <= segment.Count; i++)
{
newArray[i] = segment.Array[i];
}

显然,这只会创建原始数组中前640个字节的数组。最终,我想要一个循环,该循环遍历前640个字节并返回这些字节的数组,然后遍历下一个640个字节并返回THOSE字节的数组。这样做的目的是将消息发送到服务器,并且每个消息必须包含640个字节。我不能保证原始数组的长度可以被640整除。

谢谢

3 个答案:

答案 0 :(得分:1)

如果速度不是问题

var bytes = new byte[640 * 6];

for (var i = 0; i <= bytes.Length; i+=640)
{
   var chunk = bytes.Skip(i).Take(640).ToArray();
   ...
}

或者,您可以使用

跨度

Span<byte> bytes = arr; // Implicit cast from T[] to Span<T>

...

slicedBytes = bytes.Slice(i, 640);

BlockCopy

请注意,这可能是3个中最快的

var chunk = new byte[640]
Buffer.BlockCopy(bytes, i, chunk, 0, 640);

答案 1 :(得分:0)

如果您真的想从每个640字节块中制作新数组,那么您正在寻找.Skip.Take

这是我一起学习的一个有效示例(和一个repl of the example)。

using System;
using System.Linq;
using System.Text;
using System.Collections;
using System.Collections.Generic;

class MainClass {
public static void Main (string[] args) {
        // mock up a byte array from something
        var seedString = String.Join("", Enumerable.Range(0, 1024).Select(x => x.ToString()));
        var byteArrayInput = Encoding.ASCII.GetBytes(seedString);

        var skip = 0;
        var take = 640;
        var total = byteArrayInput.Length;

        var output = new List<byte[]>();

        while (skip + take < total) {
            output.Add(byteArrayInput.Skip(skip).Take(take).ToArray());
            skip += take;
        }

        output.ForEach(c => Console.WriteLine($"chunk: {BitConverter.ToString(c)}"));
    }
}

正确地使用ArraySegment可能真的更好,除非这是学习LINQ扩展的工作。

答案 2 :(得分:0)

您可以编写这样的通用帮助方法:

public static IEnumerable<T[]> AsBatches<T>(T[] input, int n)
{
    for (int i = 0, r = input.Length; r >= n; r -= n, i += n)
    {
        var result = new T[n];
        Array.Copy(input, i, result, 0, n);
        yield return result;
    }
}

然后您可以在foreach循环中使用它:

byte[] byteArray = new byte[123456];

foreach (var batch in AsBatches(byteArray, 640))
{
    Console.WriteLine(batch.Length); // Do something with the batch.
}

或者,如果您想要批次列表,请执行以下操作:

List<byte[]> listOfBatches = AsBatches(byteArray, 640).ToList();

如果想花哨的话,可以将其设为扩展方法,但这仅在您将要大量使用的情况下才建议使用(不要为只会在一个地方调用的内容创建扩展方法! )。

在这里,我将名称更改为InChunksOf(),以使其更具可读性:

public static class ArrayExt
{
    public static IEnumerable<T[]> InChunksOf<T>(this T[] input, int n)
    {
        for (int i = 0, r = input.Length; r >= n; r -= n, i += n)
        {
            var result = new T[n];
            Array.Copy(input, i, result, 0, n);
            yield return result;
        }
    }
}

您可以这样使用:

byte[] byteArray = new byte[123456];

// ... initialise byteArray[], then:

var listOfChunks = byteArray.InChunksOf(640).ToList();

[EDIT]已将循环终止符从r > n修改为r >= n