4

部分的にバイナリ データのストリームがあり、特定のビットが文字列内の特定の位置のバイトに設定されている場合に一致させたいと考えています。

これは、いくつかのパターンで構成されている .NET を使用する既存のシステムですSystem.Text.RegularExpressions。特定のパターンが一致すると、一致によってアクションがトリガーされます。

インジケーターの 1 つがビットフィールド内でのみ使用できるデバイスに接続しています。

私が見ることができる唯一の代替手段は、そのビットが設定されているすべてのバイトの等価クラス全体を一致させることです。

これは Mettler-Toledo スケール インターフェイスです。

ストリームは次のようになります。

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

、、SWAはステータス ワード バイトでSWBSWCビット 3 に興味がありSWBます。

これらすべてのステータス ワードのビット 5 は常に 1 に設定されるため、0x20ビットが設定されていないときはスペース ( ) になります。したがって、実際には他のステータス ビットが通過しないため、( - ) と SPACE ( - ) がSWB交互に表示されます。(0x50010100000x2000100000

だから私は一致することができました..[\(all other equivalent characters]..{6}.{6}\r\0

4

4 に答える 4

2

正規表現の場合、文字は分割できない原子単位であるため、文字内のビットを一致させるには、文字クラスを作成する必要があります。

文字クラスに文字のグループを含めるか除外する方法は2つあります。のように文字を個別にリストする[asdfg]か、のように範囲を指定し[a-z]ます。

最悪の場合、グループには1ビットをカバーする128個の要素が含まれます。ただし、上位ビットを照合する場合は、範囲を使用して連続する文字をグループ化できます。

たとえば、一致するビット8は

[\u0080-\u00FF]

一致するビット7は

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

一致するビット6は

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

等々。

于 2012-08-07T18:02:37.423 に答える
1

私の理解が正しければ、可能な値SWBは (in binary)のみ001xx00xであり、正規表現を使用して (bit 3 = ) と (bit 3 = ) を区別するだけで001x000x済み0ます。あれは正しいですか?その場合、この文字クラスを使用してビット 3 = を検出できます。001x100x10

[\u0020\u0021\u0030\u0031]

これは、ビット 3 = のときを検出します1

[\u0028\u0029\u0038\u0039]

にもっと異なる可能な値があればSWB、もっと巧妙なことをする価値があるかもしれませんが、現状では、その必要はないと思います。

于 2012-08-07T17:26:42.400 に答える
0

私があなたの間違いを理解していない限り、あなたは文字列以外のもの(上記の例ではビットフィールド)に正規表現を適用しようとしています。

ストリームに正規表現マッチングを適用するメソッドにリンクしているこのスレッドを見てください。その後、データをマッチャーに正しく提供できます。

于 2012-08-07T17:19:05.233 に答える
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 ;
        }
    }

}
于 2012-08-07T19:19:34.097 に答える