C#讀取字節(jié)數(shù)組某個(gè)位的值的具體實(shí)現(xiàn)方法
一、核心原理
- 先通過
bytes[offset]獲取字節(jié)數(shù)組中指定偏移量(offset)的單個(gè)字節(jié)(對(duì)應(yīng) PLC 中的 1 個(gè)字節(jié)地址); - 再通過 按位與(
&) 運(yùn)算 + 位左移(<<) 運(yùn)算,提取該字節(jié)中指定位(bitIndex,范圍 0~7,0 表示最低位 / 最右邊,7 表示最高位 / 最左邊)的值; - 判定規(guī)則:運(yùn)算結(jié)果非 0 表示該位為 1(對(duì)應(yīng) C#
true),運(yùn)算結(jié)果為 0 表示該位為 0(對(duì)應(yīng) C#false)。
二、關(guān)鍵表達(dá)式(提取單個(gè)位的值)
這是提取指定位的核心代碼,直接可復(fù)用:
// 核心表達(dá)式:提取 bytes 數(shù)組中 offset 偏移量字節(jié)的 bitIndex 位的值 bool bitValue = (bytes[offset] & (1 << bitIndex)) != 0;
表達(dá)式逐部分拆解
| 部分 | 含義說明 |
|---|---|
bitIndex | 要提取的位索引,范圍 0~7(必須滿足 0 ≤ bitIndex ≤ 7,否則會(huì)出錯(cuò)) |
1 << bitIndex | 把數(shù)字 1 左移 bitIndex 位,生成一個(gè) “僅目標(biāo)位為 1,其余位為 0” 的掩碼(例如 bitIndex=2 時(shí),1<<2=4,對(duì)應(yīng)二進(jìn)制 00000100) |
bytes[offset] & (1 << bitIndex) | 按位與運(yùn)算:只有 “目標(biāo)位同時(shí)為 1” 時(shí),結(jié)果才非 0,其余情況結(jié)果為 0(精準(zhǔn)篩選目標(biāo)位的值) |
!= 0 | 將位運(yùn)算結(jié)果轉(zhuǎn)換為 C# 布爾值:非 0 → true(位值為 1),0 → false(位值為 0) |
三、完整代碼示例
下面提供可直接運(yùn)行的 C# 代碼,包含字節(jié)數(shù)組定義、位提取方法、場(chǎng)景演示:
using System;
class PlcBitExtraction
{
static void Main(string[] args)
{
// 示例:從 PLC 讀取的字節(jié)數(shù)組(假設(shè) bytes[0] = 0x05,對(duì)應(yīng)二進(jìn)制 00000101)
byte[] plcBytes = new byte[] { 0x05, 0x12, 0x34 };
// 需求1:提取 offset=0(第1個(gè)字節(jié))、bitIndex=0(最低位)的值
int offset1 = 0;
int bitIndex1 = 0;
bool bit1 = ExtractBitFromBytes(plcBytes, offset1, bitIndex1);
Console.WriteLine($"字節(jié){offset1}的位{bitIndex1}值:{bit1}(對(duì)應(yīng)二進(jìn)制位1)");
// 需求2:提取 offset=0、bitIndex=1 的值
int bitIndex2 = 1;
bool bit2 = ExtractBitFromBytes(plcBytes, offset1, bitIndex2);
Console.WriteLine($"字節(jié){offset1}的位{bitIndex2}值:{bit2}(對(duì)應(yīng)二進(jìn)制位0)");
// 需求3:提取 offset=0、bitIndex=2 的值
int bitIndex3 = 2;
bool bit3 = ExtractBitFromBytes(plcBytes, offset1, bitIndex3);
Console.WriteLine($"字節(jié){offset1}的位{bitIndex3}值:{bit3}(對(duì)應(yīng)二進(jìn)制位1)");
// 需求4:提取 offset=1、bitIndex=3 的值(bytes[1]=0x12 → 二進(jìn)制 00010010)
int offset4 = 1;
int bitIndex4 = 3;
bool bit4 = ExtractBitFromBytes(plcBytes, offset4, bitIndex4);
Console.WriteLine($"字節(jié){offset4}的位{bitIndex4}值:{bit4}(對(duì)應(yīng)二進(jìn)制位1)");
}
/// <summary>
/// 從字節(jié)數(shù)組中提取指定偏移量、指定位索引的位值
/// </summary>
/// <param name="bytes">原始字節(jié)數(shù)組(從 PLC 讀取的字節(jié)流)</param>
/// <param name="offset">字節(jié)偏移量(數(shù)組索引,從0開始)</param>
/// <param name="bitIndex">位索引(0~7,0=最低位,7=最高位)</param>
/// <returns>位值(true=1,false=0)</returns>
static bool ExtractBitFromBytes(byte[] bytes, int offset, int bitIndex)
{
// 合法性校驗(yàn):防止數(shù)組越界和位索引超出范圍
if (bytes == null)
throw new ArgumentNullException(nameof(bytes), "字節(jié)數(shù)組不能為null");
if (offset < 0 || offset >= bytes.Length)
throw new ArgumentOutOfRangeException(nameof(offset), "字節(jié)偏移量超出數(shù)組范圍");
if (bitIndex < 0 || bitIndex > 7)
throw new ArgumentOutOfRangeException(nameof(bitIndex), "位索引必須在0~7之間");
// 核心:位運(yùn)算提取指定位
byte targetByte = bytes[offset]; // 獲取指定偏移量的字節(jié)
int mask = 1 << bitIndex; // 生成位掩碼
return (targetByte & mask) != 0; // 按位與運(yùn)算,判定位值
}
}
四、運(yùn)行結(jié)果說明
上述代碼中,plcBytes[0] = 0x05(十六進(jìn)制)→ 對(duì)應(yīng)二進(jìn)制 00000101,運(yùn)行后輸出:
plaintext
字節(jié)0的位0值:True(對(duì)應(yīng)二進(jìn)制位1) 字節(jié)0的位1值:False(對(duì)應(yīng)二進(jìn)制位0) 字節(jié)0的位2值:True(對(duì)應(yīng)二進(jìn)制位1) 字節(jié)1的位3值:True(對(duì)應(yīng)二進(jìn)制位1)
完全匹配二進(jìn)制位的實(shí)際值,驗(yàn)證了提取邏輯的正確性。
五、補(bǔ)充說明
- 位索引順序:PLC 中常用的位編號(hào)(如 I0.0、I0.1)通常對(duì)應(yīng)
bitIndex=0、bitIndex=1,與上述代碼的位索引一致; - 批量提取:若需提取 1 個(gè)字節(jié)對(duì)應(yīng)的 8 個(gè)位,可通過循環(huán)
bitIndex從 0 到 7 依次調(diào)用提取方法; - PLC 場(chǎng)景適配:該方法完全適配 Sharp7、S7NetPlus 等主流 PLC 通信庫(kù),可直接集成到 PLC 數(shù)據(jù)讀取業(yè)務(wù)中。
總結(jié)
- 核心表達(dá)式:
(bytes[offset] & (1 << bitIndex)) != 0(快速提取指定位的值); - 關(guān)鍵運(yùn)算:按位與(
&)用于篩選目標(biāo)位,位左移(<<)用于生成位掩碼; - 位索引范圍:0~7(0 最低位,7 最高位),偏移量
offset為字節(jié)數(shù)組的索引; - 實(shí)際使用時(shí)需增加合法性校驗(yàn),避免數(shù)組越界和無(wú)效位索引。
到此這篇關(guān)于C#讀取字節(jié)數(shù)組某個(gè)位的值的具體實(shí)現(xiàn)方法的文章就介紹到這了,更多相關(guān)C#讀取字節(jié)數(shù)組某個(gè)位的值內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于Unity中RectTransform與transform的區(qū)別
這篇文章主要介紹了Unity中RectTransform與transform的區(qū)別,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-01-01
C#實(shí)現(xiàn)網(wǎng)絡(luò)通信共享庫(kù)NetShare的使用示例
本文主要介紹了C#實(shí)現(xiàn)網(wǎng)絡(luò)通信共享庫(kù)NetShare,網(wǎng)絡(luò)通信共享庫(kù)NetShare用于保證客戶端與服務(wù)器通信數(shù)據(jù)包的規(guī)范和統(tǒng)一,感興趣的可以了解一下2023-11-11
C#基于時(shí)間輪調(diào)度實(shí)現(xiàn)延遲任務(wù)詳解
在很多.net開發(fā)體系中開發(fā)者在面對(duì)調(diào)度作業(yè)需求的時(shí)候一般會(huì)選擇三方開源成熟的作業(yè)調(diào)度框架來滿足業(yè)務(wù)需求,但是有些時(shí)候可能我們只是需要一個(gè)簡(jiǎn)易的延遲任務(wù)。本文主要分享一個(gè)簡(jiǎn)易的基于時(shí)間輪調(diào)度的延遲任務(wù)實(shí)現(xiàn),需要的可以參考一下2022-12-12
利用C#實(shí)現(xiàn)SSLSocket加密通訊的方法詳解
這篇文章主要給大家介紹了關(guān)于如何利用C#實(shí)現(xiàn)SSLSocket加密通訊的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07

