低速の入力デバイスからの短い固定長のレコードのストリームがあります。正規表現を使用して読み取り/解析することは、ハンマーを使用してネジを駆動するように見えます。
を使用してデータをカスタムクラスに読み込み、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 ;
}
}
}