C#中基于位的BinaryWriter

Orv*_*ing 6 c# binarywriter

我正在研究基于位的B/W/Greyscale预编译字体格式,并且在阅读或编写格式时遇到了问题,(我无法确定问题的位置.(我确实有基于B/W位的版本工作,但是别名字体看起来不太好,正如您可以想象的那样,特别是在使用320x200像素屏幕时))但是决定只使用BinaryWriter比写入更容易当我拉动图像数据时,一个bool [].

文件中像素的基本格式如下所示:

1 - 白色像素(最短,因为这将是大多数像素)

00 - 黑色像素(无理由为纯黑色像素写入10位,其中有合理的数量)

01 - 灰度像素,后跟1个字节,描述像素的阴影

现在,编写所需信息的一切都很好,花花公子,因为这是全部字节,但默认的.Net 4.0 BinaryWriter将布尔值写为完整字节,并且可以想象,这会否定基于位的使用格式.所以我想知道,有没有BinaryWriter,(和BinaryReader)实现那里的基于位的

编辑:我最终创建了自己的.(请参阅代码的答案.)

Jon*_*eet 6

我不相信框架中有任何东西,不,不.基本上你需要写一个类来包装一个BinaryWriter(或只是一个流)和"到目前为止写入的字节"和书面的位数.当位数达到8时,将字节写入基础流并清除.

编辑:OP发布了以下建议的可能和可行的实施方案.


Orv*_*ing 5

我最后写了自己的,所以他们在这里.

BinaryWriter(我只是覆盖了我需要的那些)

private class BinaryWriter : System.IO.BinaryWriter
{
    private bool[] curByte = new bool[8];
    private byte curBitIndx = 0;
    private System.Collections.BitArray ba;

    public BinaryWriter(Stream s) : base(s) { }

    public override void Flush()
    {
        base.Write(ConvertToByte(curByte));
        base.Flush();
    }

    public override void Write(bool value)
    {
        curByte[curBitIndx] = value;
        curBitIndx++;

        if (curBitIndx == 8)
        {
            base.Write(ConvertToByte(curByte));
            this.curBitIndx = 0;
            this.curByte = new bool[8];
        }
    }

    public override void Write(byte value)
    {
        ba = new BitArray(new byte[] { value });
        for (byte i = 0; i < 8; i++)
        {
            this.Write(ba[i]);
        }
        ba = null;
    }

    public override void Write(byte[] buffer)
    {
        for (int i = 0; i < buffer.Length; i++)
        {
            this.Write((byte)buffer[i]);
        }
    }

    public override void Write(uint value)
    {
        ba = new BitArray(BitConverter.GetBytes(value));
        for (byte i = 0; i < 32; i++)
        {
            this.Write(ba[i]);
        }
        ba = null;
    }

    public override void Write(ulong value)
    {
        ba = new BitArray(BitConverter.GetBytes(value));
        for (byte i = 0; i < 64; i++)
        {
            this.Write(ba[i]);
        }
        ba = null;
    }

    public override void Write(ushort value)
    {
        ba = new BitArray(BitConverter.GetBytes(value));
        for (byte i = 0; i < 16; i++)
        {
            this.Write(ba[i]);
        }
        ba = null;
    }

    private static byte ConvertToByte(bool[] bools)
    {
        byte b = 0;

        byte bitIndex = 0;
        for (int i = 0; i < 8; i++)
        {
            if (bools[i])
            {
                b |= (byte)(((byte)1) << bitIndex);
            }
            bitIndex++;
        }

        return b;
    }
}
Run Code Online (Sandbox Code Playgroud)

而且,BinaryReader再一次,我只是覆盖了我需要的方法.

private class BinaryReader : System.IO.BinaryReader
{
    private bool[] curByte = new bool[8];
    private byte curBitIndx = 0;
    private BitArray ba;

    public BinaryReader(Stream s) : base(s)
    {
        ba = new BitArray(new byte[] { base.ReadByte() });
        ba.CopyTo(curByte, 0);
        ba = null;
    }

    public override bool ReadBoolean()
    {
        if (curBitIndx == 8)
        {
            ba = new BitArray(new byte[] { base.ReadByte() });
            ba.CopyTo(curByte, 0);
            ba = null;
            this.curBitIndx = 0;
        }

        bool b = curByte[curBitIndx];
        curBitIndx++;
        return b;
    }

    public override byte ReadByte()
    {
        bool[] bar = new bool[8];
        byte i;
        for (i = 0; i < 8; i++)
        {
            bar[i] = this.ReadBoolean();
        }

        byte b = 0;
        byte bitIndex = 0;
        for (i = 0; i < 8; i++)
        {
            if (bar[i])
            {
                b |= (byte)(((byte)1) << bitIndex);
            }
            bitIndex++;
        }
        return b;
    }

    public override byte[] ReadBytes(int count)
    {
        byte[] bytes = new byte[count];
        for (int i = 0; i < count; i++)
        {
            bytes[i] = this.ReadByte();
        }
        return bytes;
    }

    public override ushort ReadUInt16()
    {
        byte[] bytes = ReadBytes(2);
        return BitConverter.ToUInt16(bytes, 0);
    }

    public override uint ReadUInt32()
    {
        byte[] bytes = ReadBytes(4);
        return BitConverter.ToUInt32(bytes, 0);
    }

    public override ulong ReadUInt64()
    {
        byte[] bytes = ReadBytes(8);
        return BitConverter.ToUInt64(bytes, 0);
    }
}
Run Code Online (Sandbox Code Playgroud)