VBnet访问字节的各个位// // BitArray的长度和计数是否等于字节值?

时间:2019-03-06 15:28:25

标签: vb.net byte bitarray

我正在尝试与接受/发送16位值的PLC通信,每个位都允许进行检查或不进行检查。

为此,我一直在尝试使用.Net BitArray,但结果却不成功。

底层结构由两个字节的数组组成,两个字节均初始化为0。

当我使用这些字节之一创建一个新的位数组时,我希望得到一个将8个值设置为false的数组。 情况并非如此

字节值为0时,位数组的长度和计数也为零。尽管我可以假定前导零被删除了,但这似乎很违反直觉。

当我使用一个值为200的字节创建位数组时,我期望得到一个具有8个值的数组( True,True,False,False,True,False,False,False ) 。但是,我却得到了一个长度为 200 的位数组?

代码当前为:

Private FaultBits as Byte = 0
Public Sub SetBitValue(index As Integer, value As Boolean)
    Try
        If index < 0 Then
            Throw New Exception("Index is below zero!")
        End If

        If index > 7 Then
            Throw New Exception("Index out of bounds! Maximum allowed index value is 7")
        End If

        'If BitConverter.IsLittleEndian Then
            'ToDo
        'End If

        Dim bitArray_Section As BitArray = Nothing

            bitArray_Section = New BitArray(FaultBits)
            'bitArray_Section.Length = 8  'Truncates incorrectly
            bitArray_Section.Item(index) = value 'Set the individual bit
            FaultBits = ConvertToByte(bitArray_Section) 'Set back to byte


    Catch ex As Exception
        Throw New Exception("clsFaultBits : SetBitValue : w. Index " & index & " : Exception : " & ex.Message())
    End Try
End Sub

与get等效:

 Public Function GetBitValue(index As Integer) As Boolean
    Try
        If index < 0 Then
            Throw New Exception("Index is below zero!")
        End If

        If index > 7 Then
            Throw New Exception("Index out of bounds! Maximum allowed index value is 7")
        End If


        Dim bitArray_Section As BitArray = Nothing

            bitArray_Section = New BitArray(FaultBits)
            'bitArray_Section.Length = 8
            Return bitArray_Section.Item(index)

    Catch ex As Exception
        Throw New Exception("clsFaultBits : GetBitValue : w. Index " & index & " : Exception : " & ex.Message())
    End Try
End Function

convert函数,我以为长度为8,这是错误的:

Public Function ConvertToByte(bits As BitArray) As Byte
    Try
        If bits.Count <> 8 Then
            Throw New Exception("Invalid amount of bits!")
        End If

        Dim returnbyte(1) As Byte
        bits.CopyTo(returnbyte, 0)
        Return returnbyte(0)
    Catch ex As Exception
        Throw New Exception("clsFaultBits : ConvertToByte : Exception : " & ex.Message())
    End Try
End Function
  

ByteValue :: BitarrayLength /计数

     

0 :: 0/0

     

200 :: 200/200

     

10 :: 10/10

我想完成的事情:

  

接收一个字节(1-0-0-1-0-0-1-0)

     

通过读取各个位来在程序中启用布尔值:   Check1,Check4,Check7

     

设置从0-0-0-0-0-0-0-0开始的输出字节的各个位

     

打开5:0-0-0-0-1-0-0-0

     

打开2:0-1-0-0-1-0-0-0

     

发送字节

我完全滥用BitArray类吗?我究竟做错了什么? 是什么让我可以在不陷入混乱的情况下更改单个位的值?

为什么BitArray的长度/计数与Byte相同,而不是由Byte组成的位数?

我知道代码尚未考虑字节顺序。

预先感谢


已解决:

我没有意识到向BitArray发送一个非数组字节会将其隐式转换为整数,因此它创建了一个长度/计数相等的BitArray值为字节。现在完全有意义了。

这也使我意识到我的隐式强制转换的编译器警告不会触发,因为Byte to Integer不被视为隐式的,因为通常在发生隐式强制转换时都会得到通知。

感谢您的帮助!

2 个答案:

答案 0 :(得分:0)

我不确定BitArray类是否是您所需要的。无论如何,您不能从Integer值创建BitArray。例如,语句New BitArray(200)将创建200个项的BitArray,所有项均设置为0。 如果您需要发送16位值,我认为使用UShort(也称为UInt16)数据类型代替BitArray并使用@djv建议检查单个位会更简单。要设置位,您必须使用一些“二进制”代数和And运算符。记住要始终使用无符号数据类型,并且要注意位数是从右开始的。

答案 1 :(得分:0)

不幸的是,BitArray不允许您与16位值之间进行转换。

但是,它确实适用于Byte()和Integer()。

所以我们可以从32位整数转换为32位整数,这应该可以正常工作。

也不清楚您如何拥有原始数据。是两个单独的字节,还是单个16位值?

我将假定一个未分配的16位值。

因此我们将获得以下代码:

Sub Testset()

    Dim i16 As UInt16
    i16 = 255
    SetBits(i16, 9, False)
    SetBits(i16, 9, True)

    Debug.Print(GetBits(i16, 9).ToString)

End Sub

上面的输出

00000000 11111111
00000010 11111111
True

这两个例程是:

Public Sub SetBits(ByRef My16Bits As UInt16, MyINdex As Integer, MyValue As Boolean)

    ' toss the passed 16 bits into a 32 bit interger 
    ' we do this, since the conversion routines only work
    ' for built in primitaves ike byte() or integer(). 

    Dim My32(0) As Integer
    My32(0) = My16Bits

    Dim My32Bits As New BitArray(New Integer() {My32(0)})

    My32Bits(MyINdex) = MyValue

    ' now convert bit array back to our 32 bit integer
    My32Bits.CopyTo(My32, 0)

    ' now copy our 32 bit interger back to that 16 bit
    My16Bits = My32(0)

    For i = 15 To 0 Step -1
        Debug.Write(IIf(My32Bits(i), "1", "0"))
        If i = 8 Then Debug.Write(" ")
    Next i
    Debug.Print("")

End Sub

Public Function GetBits(My16Bits As UInt16, MyIndex As Integer) As Boolean

    ' convert Int16 to bit array
    Dim My32(0) As Integer
    My32(0) = My16Bits
    Dim My32Bits As New BitArray(New Integer() {My32(0)})

    Return My32Bits(MyIndex)

End Function

当然可以删除显示值的循环。

如果在您希望位数组以一种或另一种方式转换之前必须被称为“多次”-那么您可以将转换为位数组作为单独的例程分离出来,并将其传递给获取/设置位例程,然后执行代码的最终调用,将bitArrary转换回Int16值。这实际上取决于您期望获得/设置位的次数。所以1或2次,然后以上就可以了。如果必须始终测试许多位并设置许多位,则在调用+使用两个例程设置/获取值之前,将值转换为位数组。因此,可以将与位数组之间来回转换的代码分离为单独的代码。