繁体   English   中英

将字节数组拆分为多个二进制块

[英]Splitting byte array into multiple binary chunks

我有一个要读取的二进制文件。 让我们说它的“foo.bin”。 我想将所有字节读入一个字节数组。
byte[] data = File.ReadAllBytes("foo.bin")
我想将这些字节拆分为长度为 x 的二进制数。
(使用自定义 class BinaryChunk,但任何类型的 binary / bool[] / byte[] 都可以正常工作。)

struct BinaryChunk { 
    bool[] data,
    int size
} 

BinaryChunk[] binaryChunks = SplitDataIntoBinaryChunksOfSize(data, x)

*请注意,“x”是位,而不是字节。

万一你仍然不知道我在说什么的例子:
(出于显而易见的原因,将“SplitDataIntoBinaryChunksOfSize”缩短为“SplitData”)

bool[] foo = new bool[]{0b11100110, 0b00010110};
SplitData(foo, 3) //-> 111, 001, 100, 001, 011, 000
//   1 1 1 0 0 1 1 0;0 0 0 1 0 1 1 0XXXXXXXXXXXXXXXX
//-> 1 1 1;0 0 1;1 0 0;0 0 1;0 1 1;0 0 0
SplitData(foo, 12) //-> 111001100001, 011000000000
//   1 1 1 0 0 1 1 0;0 0 0 1 0 1 1 0XXXXXXXXXXXXXXXX
//-> 1 1 1 0 0 1 1 0 0 0 0 1;0 1 1 0 0 0 0 0 0 0 0 0

正在考虑使用BitArray ,但我使用它还不够了解如何使用它。 有人有什么想法吗?

编辑:如果有人需要,我猜这是一个快速的解决方案

class BinaryStream {
            //binary data in bytes
            byte[] data;
            //length of data
            int size;

            public BinaryStream(byte[] data) {
                this.data = data;
                this.size = data.Length;
            }

            public void MoveBytes(int splicesize) {
                //moves the binarystream to the left (<<) in bytes
                size -= splicesize;
                byte[] cutdata = new byte[size];
                for (int i = 0; i < size; i++) { cutdata[i] = data[i + splicesize]; }
                data = cutdata;
            }

            public byte this[int membytes] {
                //gets the byte at index unless its not in the array then its 0
                get { return membytes < size ? data[membytes] : byte.MinValue; }
                set { if (membytes < size) data[membytes] = value; }
            }

            public static BinaryStream operator <<(BinaryStream binstream, int membits) {
                //a left shift operator (in bits)
                binstream.MoveBytes(membits / 8);
                membits %= 8;
                if (membits == 0) return binstream;

                for (int i = 0; i < binstream.size; i++) {
                    //moves the byte at index i, then grabs the next item and appends it
                    binstream[i] <<= membits;
                    binstream[i] |= (byte) (binstream[i + 1] >> (8 - membits));
                }
                return binstream;
            }
        }

上面是一个简单的BinaryStream class (有点类似于Queue<bool> ),还没有太多功能,因为它只是为了帮助解决问题。

临时解决方案:

byte[][] SplitData(byte[] data, int bits) {
        //setup
        byte[][] split = new byte[data.Length * 8 / bits][];
        int chunkSize = bits / 8 + 1; //chunksize in bytes
        BinaryStream bstream = new BinaryStream(data);

        for (int i = 0; i < split.Length; i++) {
            split[i] = new byte[chunkSize];
            int copy = bits; //number of bits to copy
            int j = 0; //index at split[] to copy to
            while (copy > 0) {
                if (copy < 8) {
                    //copy less than a byte
                    split[i][j] = (byte) ((bstream[0] & (255 << (8 - copy))) >> (8 - copy));
                    bstream <<= copy;
                } else {
                    //copy a full byte
                    split[i][j] = bstream[0];
                    bstream.MoveBytes(1);
                }
                copy -= 8;
                j++;
            }
        }
        return split;
    }

时间复杂度:O(n^2) 其中 n 是数据长度。 空间复杂度:O(n),其中 n 是数据长度。

不是最好的解决方案,也不是优雅的,但它现在有效。

使用 IEnumerables 的解决方案:

IEnumerable<bool[]> SplitDataIntoBinaryChunksOfSize(byte[] data, int x)
{
    var currentId = 0;
    var currentArray = new bool[x];
    foreach (var bit in EnumerateBits(data))
    {
        currentArray[currentId] = bit;
        currentId++;
        if(currentId == x)
        {
            yield return currentArray;
            currentArray = new bool[x];
            currentId = 0;
        }
    }
    if(currentId > 0)
        yield return currentArray;
    
}

private static readonly int[] bits = { 128, 64, 32, 16, 8, 4, 2, 1 };

IEnumerable<bool> EnumerateBits(byte[] data)
{
    foreach (var d in data)
        foreach (var b in bits)
            yield return Convert.ToBoolean(d & b);
}

在 C# 6 中,它甚至更简单:

IEnumerable<bool[]> SplitDataIntoBinaryChunksOfSize(byte[] data, int x)
{
    return Enumerable.Chunk(EnumerateBits(data), 3);
}

private static readonly int[] bits = { 128, 64, 32, 16, 8, 4, 2, 1 };

IEnumerable<bool> EnumerateBits(byte[] data)
{
    foreach (var d in data)
        foreach (var b in bits)
            yield return Convert.ToBoolean(d & b);
}

但是在那个解决方案中,如果有剩余数据,最后一个数组会更小。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM