gpt4 book ai didi

c# - 以编程方式为多个字节上的相关位创建位掩码

转载 作者:行者123 更新时间:2023-11-30 16:40:55 25 4
gpt4 key购买 nike

我正在处理一个非常长的二进制字符串,它包含的“字段”可以是 2 到 32 位长的任何内容。所以在某些情况下,一个“字段”可以跨越多个不均匀的字节。

我设法读出了所有数据,但现在我正在编辑和切换数据。这是一个 12 位字段的当前工作示例,从整个字节开始:

public class CardSectionProperty
{
public CardSectionProperty(CardDataContainer data, MapItem mapItem)
{
Data = data;
Start = mapItem.Position;
Length = mapItem.Length;
}

public CardDataContainer Data { get; } // A simple container for the binary string of the whole card.

public int Start { get; }

public int Length { get; }

public void SetValue(long value)
{
var relevantBits= 0xFF0F; // <- I think this mask need to change depending on the field size and position in the binary string.
var newValue = (int)value;
var oldValue = (int)GetValue();
var bitsToKeep = (~relevantBits) & oldValue;
var newValueCorrected = Switch16BitEndianness(newValue) | bitsToKeep;
SetValue(Convert.ToString(newValueCorrected, 2));
}

private void SetValue(string binaryValue)
{
var builder = new StringBuilder(Data.BinaryData);
builder.Remove(Start, binaryValue.Length);
builder.Insert(Start, binaryValue);
Data.BinaryData = builder.ToString();
}

private int Switch16BitEndianness(int x)
{
return ((x & 0xFF00) >> 8) | ((x & 0x00FF) << 8);
}
}

这里的掩码是 0xFF0F (1111 1111 0000 1111) 这很容易理解,因为我们关心的是 12 位。但是,以编程方式创建此掩码的最简单方法是什么?正如我所说,它可以是非常随机的,有时我们可以跨越三个字节(从第一个开始使用 2 位,然后使用 8 个,然后从最后一个开始使用 2 个,等等)。

或者有更好的方法吗?

编辑:添加了更多代码以使示例更易于理解。

最佳答案

这里的主要问题实际上是......这些位字段是什么?从您的问题中,您的数据来自何处及其含义不是很清楚。

一般来说,这些位将分别代表一个特定的 bool 值来启用和禁用,因此它们也应该分别有一个特定的名称。这表示的正常方式是使用 [Flags] 枚举。它们允许您建立值,其中每个位标志都是您启用的命名选项。 .Net 框架中已经使用了大量这些内容。

基本上,标志枚举是定义为包含可以组合的位的枚举。您只需为您使用的每个位分配一个名称,并将它们与 OR 运算结合起来。

[Flags]
public enum BitMask
{
Empty = 0x00, // 0000 0000 0000 0000
BitOne = 0x01, // 0000 0000 0000 0001
BitTwo = 0x02, // 0000 0000 0000 0010
BitThree = 0x04, // 0000 0000 0000 0100
BitFour = 0x08, // 0000 0000 0000 1000
BitFive = 0x10, // 0000 0000 0001 0000
BitSix = 0x20, // 0000 0000 0010 0000
BitSeven = 0x40, // 0000 0000 0100 0000
BitEight = 0x80, // 0000 0000 1000 0000
// etc...
}

您甚至可以在其中放置常用的预设,例如 BitsFourAndFive = 0x18,这非常方便。当然,您的实际选项应该具有它们实际代表的 bool 值的名称。

然后你可以简单地结合你的位

BitMask mask = BitMask.BitTwo | BitMask.BitFive | BitMask.BitEight;

我假设你知道这些,因为你在你的代码中使用它们,但无论如何......要从掩码中删除一点,对反转值使用 AND 运算:

mask &= ~BitMask.BitTwo;

...并检查掩码中是否有位:

Boolean isTwo = (mask & BitMask.BitTwo) != 0;

最后,要获得您的实际值...只需将其转换为整数即可。

Int32 maskvalue = (Int32)mask;

同样的事情显然也可以反过来做;如果您从输入中读取了一个值,您可以将其转换为 BitMask。读取值后可能的“第二位已启用”检查:

Int32 readValue = ReadValue(); // wherever this comes from
Boolean isTwo = ((BitMask)readValue & BitMask.BitTwo) != 0;

或者,您可以将 BitMask 枚举条目转换为 Int32;这也行。

这是我的一个项目中的一个真实示例,一堆游戏 sprite 类使用它来公开它们包含什么样的图像,以及它们可以使用什么样的图像作为输入以保存为该 sprite 类型:

[Flags]
public enum FileClass
{
None = 0x00,
Image1Bit = 0x01,
Image4Bit = 0x02,
Image8Bit = 0x04,
ImageIndexed = 0x07,
ImageHiCol = 0x08,
Image = 0x0F,
}

如您所见,为了保存输入数据,我将快速预设 ImageImageIndexed 组合在一起,以快速指示输入根本不重要,或者需要至少低至 8 位。

关于c# - 以编程方式为多个字节上的相关位创建位掩码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50196897/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com