我有一个字节数组,实际上是像这样的二进制值
byte[] buf = new byte[] { 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
二进制表示为1111 1110
(0xFF
= 0
,0xF0
= 1
)。
需要从中构建的整数或字节的值为0xFE
(254)。
我考虑过将buf
转换为1
和0
s的字符串,然后再转换为整数,但必须有更优雅的方法来完成二进制操作
已知完美地执行此操作的Pascal代码是(使用字符串):
if NumberOfBytes > 0 then begin // there was a response
for c := Length(Str) downto 1 do begin
Ch := Str[c];
if (ord(ch) AND 2) = 0 then begin
Sin := Sin + '0';
end else begin
Sin := Sin + '1';
end;
INC(Teller);
if (Teller mod 8) = 0 then begin
N := BinaryStrToByte(Sin);
Edit2.Text := Edit2.Text + ByteHex(N) + ' ' ;
Sin := '';
end;
end;
由于行为的某些差异,C代码似乎也没有移植到C#:
for(bytes = 0; bytes < len; bytes++)
{
newByte=0;
for(bits=0; bits<8; bits++)
{
newByte >>= 1;
if(inBuf[0]==0xff)
{
newByte |= 0x80;
}
}
pBuf[bytes]=newByte;
}
我希望有效地遍历原始数组,然后将真正的二进制0
或1
放入int
或byte
,具体取决于我是否{{}在当前位置输入1}}或0xF0
。
答案 0 :(得分:1)
这可能会起到作用:
public static void Main()
{
byte[] buf = new byte[] { 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
byte result = 0;
foreach(var b in buf.Reverse())
{
result <<= 1;
if(b == 0xFF) result |= 1;
}
Console.WriteLine(result);
}
答案 1 :(得分:1)
具有最少量分支(和LINQ调用)的方法:
byte result = 0x00;
foreach(byte b in buf) {
result >>= 0x01;
byte bs = b;
bs <<= 0x07;
result |= bs;
}
此代码假设eac字节的最低有效位确定0
(如果0xf0=1111 0000
)是1
(在0xff=1111 1111
的情况下)应该加入。
Mono C#Interactive shell中的演示:
csharp> byte[] buf = new byte[] { 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
csharp> byte result = 0x00;
csharp> foreach(byte b in buf) {
> result >>= 0x01;
> byte bs = b;
> bs <<= 0x07;
> result |= bs;
> }
csharp> result.ToString("X");
"FE"
答案 2 :(得分:0)
这是一个更通用的LINQ解决方案:
将字节转换为位的方法(在本例中表示为布尔值)
public static IEnumerable<Boolean> BytesToBooleans(IEnumerable<Byte> bytes)
{
if (bytes == null)
throw new ArgumentNullException("bytes");
return bytes
.Select(b =>
{
if (b == 0xF0)
return false;
if (b == 0xFF)
return true;
throw new ArgumentException();
});
}
将布尔值解释为从最低位开始的位的方法:
public static IEnumerable<Byte> BooleansAsBitsFromLowest(this IEnumerable<Boolean> bits)
{
if (bits == null)
throw new ArgumentNullException("bits");
Int32 bitsInByte = 0;
Byte curByte = 0;
foreach (var bit in bits)
{
var mask = (Byte)(bit ?
0x1 : 0x0);
mask = (Byte)(mask << bitsInByte);
curByte |= mask;
bitsInByte++;
if (bitsInByte == 8)
{
yield return curByte;
curByte = 0;
bitsInByte = 0;
}
}
if (bitsInByte != 0)
yield return curByte;
}
以下是用法:
byte[] buf = new byte[] { 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
var bytesFromBits = BytesToBooleans(buf)
.BooleansAsBitsFromLowest();
foreach (var resultingByte in bytesFromBits)
{
Console.WriteLine(resultingByte.ToString("X2"));
}