2012-08-07 126 views
3

我有一個部分二進制數據流,我想匹配時,在字符串中某個位置的某個字節中設置了某個位。RegEx帶位掩碼?

這在使用System.Text.RegularExpressions其被配置成與數量的圖案.NET現有系統 - 當特定模式匹配,則匹配觸發一個動作。

我接口到一個設備,其中的指標之一是唯一可用的位字段內。

我能看到的唯一的選擇是符合整個等價類所有有位設置的字節數。

這是一個梅特勒 - 託利多量表接口。

流是這樣的:

STX 
SWA 
SWB 
SWC 
WEIGHT (6 bytes ASCII) 
TARE (6 bytes ASCII) 
0x0D (CR) 
(Optional checksum) 

SWASWBSWC是狀態字字節,我很感興趣的SWB第3位。

他們總是設置位5:1,在所有這些狀態字,所以它是一個空間(0x20)時,沒有位被設置。所以實際上沒有其他狀態比特通過,SWB(0x50-01010000)和SPACE(0x20-00100000)之間的交替變化。實際上,比例也可能在我不在乎的其他狀態中發送比特0和4關於。

所以我可以匹配..[\(all other equivalent characters]..{6}.{6}\r\0

+2

這是對我來說太抽象:)你能也許用一個例子澄清你的問題? – dasblinkenlight 2012-08-07 16:59:11

回答

0

除非我明白你錯了 - 你正在尋找應用上不是字符串的東西正則表達式(在你上面的例子,一個位域)。

this線鏈接到一個方法來應用規則表達式中的流匹配。然後您可以提供數據的匹配正確即

1

如果我理解正確的話,對於SWB唯一可能的值(二進制)001xx00x,你只需要使用正則表達式來區分001x000x(位3 = 0 )從001x100x(位3 = 1)。那是對的嗎?如果是這樣,那麼你可以使用這個字符類檢測時,位3 = 0

[\u0020\u0021\u0030\u0031] 

而這一次檢測時,位3 = 1

​​

如果有更多不同的可能值對於SWB,那麼它可能值得做更聰明的事情,但事實是,我不認爲有這種需要。

+0

這是正確的。如果可能設置其他位,我將不得不添加其他等效字節。 – 2012-08-07 17:36:25

+0

實際上,我將不得不重新編譯這個東西,使用一些替代的邏輯/配置,這個規模不依賴於簡單的正則表達式,並試圖找出如何在稍後將其重構爲一致的配置。 – 2012-08-07 17:38:47

+0

@CadeRoux:Re:創建一個備用的非正則表達式配置:是的,我認爲這是正確的選擇。 :-) – ruakh 2012-08-08 12:25:42

1

當涉及到正則表達式,字符是一個不可分割的組成單位,所以你需要以一個字符內匹配位,創建一個字符類。

有兩種方法可以在字符類中包含或排除一組字符 - 通過單獨列出它們(如[asdfg]),或者指定一個範圍(如[a-z])。

在最糟糕的情況下,您的組將包含128個覆蓋單個位的元素。但是,如果您匹配較高位,則可以使用範圍將連續字符組合在一起。

例如,匹配位8是

[\u0080-\u00FF] 

匹配位7是

[\u0040-\u007F\u00C0-\u00FF]` 

匹配位6是

[\u0020-\u003F\u0060-\u007F\u0060-\u007F\u00E0-\u00FF] 

等。

0

您已經從低速輸入設備獲得了一串短而長的固定長度的記錄。使用正則表達式來讀取/解析這個看起來像使用錘子來驅動螺絲釘。

爲什麼不只是將BinaryReader的數據讀入自定義類並將其作爲對象進行處理?更容易理解,更易於維護。

事情是這樣的:

static void Main(string[] args) 
    { 
     using (Stream  s  = OpenStream()) 
     using (BinaryReader reader = new BinaryReader(s , Encoding.ASCII)) 
     { 
      foreach (ScaleReading reading in ScaleReading.ReadInstances(reader)) 
      { 
       if (!reading.IsValid) continue ; // let's just skip invalid data, shall we? 
       bool isInteresting = (reading.StatusB & 0x08) == 0x08 ; 
       if (isInteresting) 
       { 
        ProcessInterestingReading(reading) ; 
       } 
      } 
     } 

     return; 
    } 

其中ScaleReading看起來是這樣的:

class ScaleReading 
{ 

    private ScaleReading(byte[] data , int checkSum) 
    { 
     this.Data    = data       ; 
     this.CheckSum   = checkSum      ; 
     this.ComputedCheckSum = ComputeCheckSumFromData(data) ; 

     this.STX  = data[0] ; 
     this.StatusA = data[1] ; 
     this.StatusB = data[2] ; 
     this.StatusC = data[3] ; 
     this.Weight = ToInteger(data, 4, 6) ; 
     this.Tare = ToInteger(data, 10,6) ; 
     this.CR  = data[16] ; 

    } 

    private int ToInteger(byte[] data , int offset , int length) 
    { 
     char[] chs = Encoding.ASCII.GetChars(data , offset , length) ; 
     string s  = new String(chs) ; 
     int value = int.Parse(s) ; 

     return value ; 
    } 

    private int ComputeCheckSumFromData(byte[] data) 
    { 
     //TODO: compute checksum from data octets 
     throw new NotImplementedException(); 
    } 

    public bool IsValid 
    { 
     get 
     { 
      bool isValid = ComputedCheckSum == CheckSum 
         && STX    == '\x0002' // expected STX char is actually STX 
         && CR    == '\r'  // expected CR char is actually CR 
         ; 
      return isValid ; 
     } 
    } 

    public byte[] Data    { get ; private set ; } 
    public int ComputedCheckSum { get ; private set ; } 
    public int CheckSum   { get ; private set ; } 

    public byte STX  { get ; private set ; } // ? 
    public byte StatusA { get ; private set ; } // might want to make each of status word an enum 
    public byte StatusB { get ; private set ; } // might want to make each of status word an enum 
    public byte StatusC { get ; private set ; } // might want to make each of status word an enum 
    public int Weight { get ; private set ; } 
    public int Tare { get ; private set ; } 
    public byte CR  { get ; private set ; } 

    public static ScaleReading ReadInstance(BinaryReader reader) 
    { 
     ScaleReading instance = null; 
     byte[]  data  = reader.ReadBytes(17); 

     if (data.Length > 0) 
     { 
      if (data.Length != 17) throw new InvalidDataException() ; 

      int checkSum = reader.ReadInt32() ; 
      instance  = new ScaleReading(data , checkSum); 

     } 

     return instance; 

    } 

    public static IEnumerable<ScaleReading> ReadInstances(BinaryReader reader) 
    { 
     for (ScaleReading instance = ReadInstance(reader) ; instance != null ; instance = ReadInstance(reader)) 
     { 
      yield return instance ; 
     } 
    } 

} 
+0

因爲當我有其他工作要做時,我不想改變另一個古怪的書面傳統程序。所以是的,現在它有一個特殊的模式來完成你寫的東西,希望這個源代碼是正確的版本,這個版本會很好的測試。 – 2012-08-07 19:37:25