![](/img/trans.png)
[英]Splitting ZipFile into multiple small chunks and combining Chunks again to create ZipFile
[英]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.