C# 读取字节数组中不同长度位字段的最简单方法是什么?

C# 读取字节数组中不同长度位字段的最简单方法是什么?,c#,logic,binaryfiles,bit,C#,Logic,Binaryfiles,Bit,我正在尝试读取一个二进制文件,一种使用不同大小的位字段来引用不同颜色的图像格式,这样做是使用调色板的字典。 例如 使用以下调色板: 二进制数据如下所示 问题是,当一个用户读取这个文件时,我得到一个字节[],我不知道如何用字节处理这些可变长度字段。主要问题是在读取字节[0]时使用上面的示例,我得到了01011011,通过这个示例,我可以将部分数据转换为FFFFFF、FF0000、FF00DC,但剩下的是00000011 所以,问题是,我如何将这个字节的剩余部分与下一个字节连接起来,以便能够读取完整

我正在尝试读取一个二进制文件,一种使用不同大小的位字段来引用不同颜色的图像格式,这样做是使用调色板的字典。 例如

使用以下调色板:

二进制数据如下所示

问题是,当一个用户读取这个文件时,我得到一个字节[],我不知道如何用字节处理这些可变长度字段。主要问题是在读取字节[0]时使用上面的示例,我得到了01011011,通过这个示例,我可以将部分数据转换为FFFFFF、FF0000、FF00DC,但剩下的是00000011

所以,问题是,我如何将这个字节的剩余部分与下一个字节连接起来,以便能够读取完整的代码。 例如

并正常阅读

Obs:我用的是c


编辑:这是我为无损图像压缩开发的一种格式

这是一个位读取器示例。这不是很有效,因为我返回最低位位置的读取位,然后移动以累积下一个字段

首先,一个类跟踪字节[]中的位和字节位置并返回下一位

public class BitPosition {
    int bytePos = 0;
    int bitPos = 0; // 0 - 7 only
    Byte[] data;

    public BitPosition(Byte[] src) => data = src;

    static byte[] byteBitMasks = new byte[] { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
    public int ReadNextBit() {
        if (bytePos >= data.Length)
            throw new IndexOutOfRangeException("ReadNextBit");

        int bit = (data[bytePos] & byteBitMasks[bitPos]) == 0 ? 0 : 1;
        if (++bitPos > 7) {
            bitPos = 0;
            ++bytePos;
        }
        return bit;
    }
    public bool HasMoreData => bytePos < data.Length;
}
注意:如果需要更大的标记,可以用int或uint替换byte。如果最多需要64位标记,则需要修改ColorReader以使用uint64

最后是ColorReader类,它使用压缩调色板和BitPosition类从字节[]读取颜色:


没有大小不同的钻头。一个位就是一个位,在运行C的任何东西上,它是一个字节的1/8,一个字节是8位。图像可能会使用不同的位数来表示不同的颜色,但这是不太可能的。您试图读取的具体图像格式是什么?我可能会使用BitConverter.ToInt16一次将数组中的2个字节转换为一个短的字节。提取数据,直到进入第二个字节,然后在下一个字节重新加载短路。您可能还需要考虑Big-Endian/Little-Endian。@KenWhite这是一种压缩格式。谢谢您的更正。我正在创建自己的图像格式,我知道使用不同位数并不常见,但这是轻松压缩数据的最佳方式,我不能只在16位1中转换2个字节,因为这可能会发生在序列中的2个以上的位。在读取每个字段时,可能会非常低效,并对整个字节[]进行位移位,或者效率稍低一点,在数组中使用一个字节+位指针,并使用一个例程返回给定指针和字节[]的下n位。考虑类位错{int ByTePOS;int BITPOS;空隙MOVEBYBITSINT NULBOFBITS;int ReNNBITSINT NUBROBFITS;}。
0101101110101100010111
00000011 + 10101100 = 0000001110101100
public class BitPosition {
    int bytePos = 0;
    int bitPos = 0; // 0 - 7 only
    Byte[] data;

    public BitPosition(Byte[] src) => data = src;

    static byte[] byteBitMasks = new byte[] { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
    public int ReadNextBit() {
        if (bytePos >= data.Length)
            throw new IndexOutOfRangeException("ReadNextBit");

        int bit = (data[bytePos] & byteBitMasks[bitPos]) == 0 ? 0 : 1;
        if (++bitPos > 7) {
            bitPos = 0;
            ++bytePos;
        }
        return bit;
    }
    public bool HasMoreData => bytePos < data.Length;
}
public class ColorEntry {
    public byte marker;
    public int color;
    public int sizeInBits;
}
public class ColorReader {
    BitPosition bp;

    public ColorReader(byte[] data) => bp = new BitPosition(data);

    static ColorEntry[] palette = new[] {
                new ColorEntry { marker = 0b0, color = 0xFFFFFF, sizeInBits = 1 },
                new ColorEntry { marker = 0b10, color = 0xFF0000, sizeInBits = 2 },
                new ColorEntry { marker = 0b110, color = 0xFF00DC, sizeInBits = 3 },
                new ColorEntry { marker = 0b111, color = 0xFF5A0C, sizeInBits = 3 },
            };

    public IEnumerable<ColorEntry> Colors() {
        while (bp.HasMoreData) {
            int bitsSoFar = 0;
            int numBits = 0;
            do {
                int nextBit = bp.ReadNextBit();
                ++numBits;
                bitsSoFar |= nextBit;

                var nextCE = palette.FirstOrDefault(ce => ce.sizeInBits == numBits && ce.marker == bitsSoFar);
                if (nextCE != null) {
                    yield return nextCE;
                    break;
                }
                else
                    bitsSoFar <<= 1;
            } while (true);
        }
    }
}
var data = new byte[] { 0b01011011, 0b10101100, 0b01011100 };
var cr = new ColorReader(data);
var ans = cr.Colors().Select(c => c.color).ToList();