compare byte[]

  • Thread starter Thread starter Etienne Lebeau
  • Start date Start date
E

Etienne Lebeau

Hi,
I'm looking for the easiest way to compare the content of two byte[]
for equality. Doing a "==" or Equals() compare the reference and not
the content. Any ideas?
Etienne.
 
Etienne Lebeau said:
I'm looking for the easiest way to compare the content of two byte[]
for equality. Doing a "==" or Equals() compare the reference and not
the content. Any ideas?

1) Check they're either both null or both non-null
2) Check lengths
3) Check the bytes one at a time
 
Thank you, buy I was looking if the're was a way already implemented in
the framework to do so. I think I will just wrap the Array in a
ComparableArray class that will overload the Equals() and "==" operator
and implement IComparable. I'm just wondering why this is not already
implemented in the framework due to the fact that it's so low level. Or
maybe I'm just missing something?
Etienne.
 
Hi etienne,

I have create a ByteArray Class inherited from Collection base.
I use it for low level COM communication, buffer, stream ...
It is implicitely convertible to byte[] and have some other tools like
concatenation (with byte and ByteArray), conversion to/from strings, and
comparison (just for you).

Sorry but all comments are in french (mais peut etre que ca ne vous genrea
pas)

Hope it will be usefull.

ROM
using System;

using System.Collections;

using System.Text;



namespace ROM.Utils

{


public class ByteArray : System.Collections.CollectionBase

{

#region constructors


/// <summary>

/// Contructeur a partir d'une source

/// </summary>

/// <param name="src">la source</param>

/// <param name="start">l'index de début de copie</param>

/// <param name="len">La longueur de la copie</param>

public ByteArray (ByteArray src, int start, int len) { for (int i=0; i <
len; i++) this.Add(src[i+start]); }

/// <summary>

/// Constructeur a partir d'une source

/// </summary>

/// <param name="src">la source</param>

/// <param name="start">l'index de début de copie</param>

public ByteArray (ByteArray src, int start) : this(src, start,
src.Count-start) {}

/// <summary>

/// Constructeur a partir d'une source

/// </summary>

/// <param name="src">la source</param>

public ByteArray (ByteArray src) : this(src, 0, src.Count) {}

/// <summary>

/// constructeur a partir d'un byte[]

/// </summary>

/// <param name="src">The byte[] to copy from.</param>

public ByteArray (byte[] src) { this.Add(src); }

/// <summary>

/// Constructeur a partir d'une source de type byte[]

/// </summary>

/// <param name="src">la source</param>

/// <param name="start">l'index de début de copie</param>

public ByteArray (byte[] src, int start, int len) { for (int i=0; i < len;
i++) this.Add(src[i+start]); }

/// <summary>

/// Constructeur a partir d'une source de type byte[]

/// </summary>

/// <param name="src">la source</param>

public ByteArray (byte[] src, int start) : this(src, start,
src.Length-start) {}

/// <summary>

/// constructeur a partir d'un seul byte

/// </summary>

/// <param name="b">le byte a placer a l'indew 0</param>

public ByteArray (byte b) { this.Add(b); }


/// <summary>

/// construit un ByteArray de longueur len, remplis de b

/// </summary>

/// <param name="b">le byte a copier len fois</param>

/// <param name="len">Le nombre de fois a copier le byte b</param>

public ByteArray (byte b, int len) {while (len-- > 0) this.Add(b);}

/// <summary>

/// construit un ByteArray de longueur len, replis de 0x00

/// </summary>

/// <param name="len">Le nombre de fois a copier le byte 0x00</param>

public ByteArray (int len) : this(0x00,len){}

/// <summary>

/// Constructeur apr défaut, construit un ByteArray Vide

/// </summary>

public ByteArray () {}



/// <summary>

/// constructeur a partir d'un seul byte

/// </summary>

/// <param name="b">le byte a placer a l'indew 0</param>

public ByteArray (ushort b) { this.Add(b); }

/// <summary>

/// constructeur a partir d'un seul byte

/// </summary>

/// <param name="b">le byte a placer a l'indew 0</param>

public ByteArray (uint b) { this.Add(b); }

/// <summary>

/// constructeur a partir d'un seul byte

/// </summary>

/// <param name="b">le byte a placer a l'indew 0</param>

public ByteArray (ulong b) { this.Add(b); }


#endregion

#region opérateur de collections

/// <summary>

/// Renvoie un sous ByteArray qui qui commence a l'indeice start, de
longueur len

/// </summary>

/// <param name="start">le début du sous ByteArray</param>

/// <param name="len">La longueur du sous ByteArray</param>

/// <returns>un sous ByteArray qui qui commence a l'indeice start, de
longueur len</returns>

public ByteArray SubArray (int start, int len) { return new ByteArray(this,
start, len); }

/// <summary>

/// Renvoie un sous ByteArray qui qui commence a l'indeice start

/// </summary>

/// <param name="start">le début du sous ByteArray</param>

/// <returns>un sous ByteArray qui qui commence a l'indeice start</returns>

public ByteArray SubArray (int start) { return new ByteArray(this, start); }

/// <summary>

/// Obtient ou définit l'élément de l'index spécifié.

/// cette propriété est l'indexeur de la classe

/// </summary>

/// <param name="Index">L'index de l'élément a obtenir ou a définir</param>

/// <value>L'élément à l'index spécifié</value>

/// <exception cref="ArgumentOutOfRangeException">index is not a valid index
in the list.</exception>

public byte this[int Index] { get {return (byte) this.List[Index];} set
{this.List[Index] = value;} }

/// <summary>

/// ajoute un byte au ByteArray

/// </summary>

/// <param name="val">Le byte a ajouter.</param>

/// <returns>l'index de l'élément ajouté.</returns>

public int Add(byte val) { return this.List.Add(val); }

/// <summary>

/// Decompose un ushort en 2 bytes, et els ajoute à la liste.

/// MSB d'abord, LSB ensuite. renvoie l'index de LSB.

/// </summary>

/// <param name="us">2 bytes a ajouter a au ByteArray</param>

/// <returns>L'index du LSB</returns>

public int Add(ushort us)

{

this.List.Add((byte)(us >> 8));

return this.List.Add((byte)(us & 0xFF));

}

/// <summary>

/// Decompose un uint en 2 ushort, et els ajoute à la liste.

/// MSB d'abord, LSB ensuite. renvoie l'index de LSB.

/// </summary>

/// <param name="us">4 Bytes a ajouter a au ByteArray</param>

/// <returns>L'index du LSB</returns>

public int Add(uint us)

{

this.List.Add((ushort)(us >> 16));

return this.List.Add((ushort)(us & 0xFFFF));

}

/// <summary>

/// Decompose un ulong en 2 uint, et els ajoute à la liste.

/// MSB d'abord, LSB ensuite. renvoie l'index de LSB.

/// </summary>

/// <param name="us">8-bytes a ajouter a au ByteArray</param>

/// <returns>L'index du LSB</returns>

public int Add(ulong us)

{

this.List.Add((uint)(us >> 32));

return this.List.Add((uint)(us & 0xFFFFFFFF));

}

/// <summary>

/// ajoute un byte[] au ByteArray

/// </summary>

/// <param name="bArray">le byte[] a ajouter.</param>

/// <returns>L'index du dernier élément ajouté.</returns>

public int Add(byte[] bArray)

{

if(bArray==null) return this.Count;

int i=0;

foreach (byte b in bArray)

i = this.List.Add(b);

return i;

}

/// <summary>

/// ajoute un sous byte[] a partir de l'index start et de longueur len, a la
fin du ByteArray

/// </summary>

/// <param name="bArray">le byte[] a ajouter.</param>

/// <param name="start">l'index a partir duquel ajouter.</param>

/// <param name="len">longueur de la chaine a ajouter.</param>

/// <returns>l'index du dernier element ajouté.</returns>

public int Add(byte[] bArray, int start, int len) { int i=0; while (i < len)
i = this.List.Add(bArray[start + i++]); return i; }

/// <summary>

/// Ajoute le ByteArray passé en paramètre, au ByteArray

/// </summary>

/// <param name="BL">le ByteArray a ajouter.</param>

/// <returns>L'index du dernier byte ajouté.</returns>

/* public int Add(ByteArray B)

{

if (B == null)

return;


int i = this.Count;

foreach (byte b in B)

i = this.Add(b);

return i;

}*/

public int Add(string ascii)

{

return this.Add(new ByteArray(ascii));

}

/// <summary>

/// Retourne l'index du premier élément dont la valeur est val.

/// </summary>

/// <param name="val">L'élement a trouver.</param>

/// <returns>l'index de val, ou -1 en cas d'échec.</returns>

public int IndexOf(byte val) { return this.List.IndexOf(val); }


/// <summary>

/// Retourne l'index du premier sous ByteArray dont la valeur est val.

/// </summary>

/// <param name="val">Le sous ByteArray</param>

/// <returns>L'index de la première occurence de val, ou -1 en cas
d'échec.</returns>

public int IndexOf(ByteArray val)

{

if(val == null) return -1;

if(val.Count == 0 || val.Count > this.Count) return -1;

for(int i = 0; i < this.Count-val.Count; ++i)

{

if(ByteArray.IsEqual(this.SubArray(i,val.Count),val))

return i;

}

return -1;

}

/// <summary>

/// Insert un element dans la liste à l'index spécifié.

/// </summary>

/// <param name="Index">L'index à inserer.</param>

/// <param name="val">la valeur a inserer.</param>

public void Insert(int Index, byte val) { this.List.Insert(Index, val); }

/// <summary>

/// Supprime la premiere occurence du byte passé en parametre.

/// </summary>

/// <param name="val">la valeur a supprimer du ByteArray.</param>

public void Remove(byte val) { this.List.Remove(val); }

/// <summary>

/// Determine si le ByteArray contient la valeur passée en paramètre

/// </summary>

/// <param name="val">la valeur a localiser</param>

/// <returns>true si la valeur est dans la liste, false sinon.</returns>

public bool Contains(byte val) { return List.Contains(val); }

#endregion

#region opérateurs de concaténation

public static ByteArray operator+(ByteArray B1, ByteArray B2)

{

ByteArray res = new ByteArray(B1);

res.Add(B2);

return res;

}

public static ByteArray operator+(ByteArray B, byte b)

{

ByteArray res = new ByteArray(B);

res.Add(b);

return res;

}

public static ByteArray operator+(byte b, ByteArray B)

{

return B+b;

}

public static ByteArray operator+(ByteArray B, byte[] b)

{

ByteArray res = new ByteArray(B);

res.Add(b);

return res;

}

public static ByteArray operator+(byte[] b, ByteArray B)

{

return B+b;

}

public static ByteArray operator+(ByteArray B, ushort b)

{

ByteArray res = new ByteArray(B);

res.Add(b);

return res;

}

public static ByteArray operator+(ushort b, ByteArray B)

{

return B+b;

}


public static ByteArray operator+(ByteArray B, uint b)

{

ByteArray res = new ByteArray(B);

res.Add(b);

return res;

}

public static ByteArray operator+(uint b, ByteArray B)

{

return B+b;

}

public static ByteArray operator+(ByteArray B, ulong b)

{

ByteArray res = new ByteArray(B);

res.Add(b);

return res;

}

public static ByteArray operator+(ulong b, ByteArray B)

{

return B+b;

}


#endregion

#region opérateurs d'inégalité

/// <summary>

/// Comparaison Bit à bit

/// </summary>

/// <param name="B1"></param>

/// <param name="B2"></param>

/// <returns></returns>

public static bool operator >=(ByteArray B1, ByteArray B2)

{

throw new Exception("ByteArray.operator>= Non Testé");

//if(B1 == null || B2 == null) throw new NullReferenceException();


//// Il faut d'abord comparer la longueur effetive (supprimer les zéros du
début).

//int ZeroB1 = 0;

//while(B1[ZeroB1++] != 0);

//int ZeroB2 = 0;

//while(B2[ZeroB2++] != 0);

//if(B1.Count - ZeroB1 > B2.Count - ZeroB2) // si B1 est plus long, il est
plus grand

// return true;

//if(B1.Count - ZeroB1 < B2.Count - ZeroB2) // si B2 est plus long il est
plus grand

// return false;



//// ensuite on compare octets par octets

//for(int i = ZeroB1; i<B1.Count; ++i)

//{

// if(B1 != B2)

// return B1 > B2;

//}

//// égalité

//return true;

}

public static bool operator<=(ByteArray B1, ByteArray B2)

{

return B2>=B1;

}

public static bool operator>(ByteArray B1, ByteArray B2)

{

return (B1>=B2) && !(B2>=B1);

}

public static bool operator<(ByteArray B1, ByteArray B2)

{

return (B2>=B1) && !(B1>=B2);

}

public static bool IsEqual(ByteArray B1, ByteArray B2)

{

if(B1 == null && B2 == null) return true;

if(B1 == null || B2 == null) return false;

if(B1.Count != B2.Count) return false;

for(int i = 0; i< B1.Count; ++i)

if(B1 != B2)

return false;

return true;

}

public static bool IsDifferent(ByteArray B1, ByteArray B2)

{

return ! IsEqual(B1,B2);

}

public bool IsEqual(ByteArray B)

{

return IsEqual(this,B);

}

public bool IsDifferent(ByteArray B)

{

return ! IsEqual(this,B);

}



#endregion

#region opérateurs binaires

public static ByteArray operator >>(ByteArray source, int BitCount)

{

throw new Exception("ByteArray operator >> Non Testé");

//ByteArray res = new ByteArray(source);

//while(BitCount-- > 0)

// source.DecalageADroite();

//return res;

}

private void DecalageADroite()

{

byte ProchaineRetenue = 0;

byte Retenue = 0;

for(int i = 0; i<this.Count; ++i)

{

ProchaineRetenue = (byte)(this%2);

this /= 2;

this += Retenue;

Retenue = (byte)(ProchaineRetenue * 0x80);

}

}

public static ByteArray operator <<(ByteArray source, int BitCount)

{

throw new Exception("ByteArray operator << Non Testé");

//ByteArray res = new ByteArray(source);

//while(BitCount-- > 0)

// source.DecalageAGauche();

//return res;

}

private void DecalageAGauche()

{

byte ProchaineRetenue = 0;

byte Retenue = 0;

for(int i = this.Count - 1 ; i>=0; ++i)

{

ProchaineRetenue = (byte)(this/0x80);

this *= 2;

this += Retenue;

Retenue = ProchaineRetenue;

}


}


public static ByteArray operator |(ByteArray B1, ByteArray B2)

{

ByteArray LePlusLong;

ByteArray LePlusCourt;

if(B1.Count >= B2.Count)

{

LePlusLong = B1;

LePlusCourt = new ByteArray(B2);

}

else

{

LePlusLong = B2;

LePlusCourt = new ByteArray(B1);

}

while(LePlusCourt.Count != LePlusLong.Count)

LePlusCourt.List.Insert(0,(byte)0);

ByteArray res = new ByteArray();

for(int i = 0;i<LePlusLong.Count; ++i)

res.Add((byte)(LePlusCourt | LePlusLong));

return res;


}

public static ByteArray operator |(ByteArray B1, byte b)

{

ByteArray res = new ByteArray(B1);

res[res.Count-1] |= b;

return res;


}

public static ByteArray operator ^(ByteArray B1, ByteArray B2)

{

ByteArray LePlusLong;

ByteArray LePlusCourt;

if(B1.Count >= B2.Count)

{

LePlusLong = B1;

LePlusCourt = new ByteArray(B2);

}

else

{

LePlusLong = B2;

LePlusCourt = new ByteArray(B1);

}

while(LePlusCourt.Count != LePlusLong.Count)

LePlusCourt.List.Insert(0,(byte)0);

ByteArray res = new ByteArray();

for(int i = 0;i<LePlusLong.Count; ++i)

res.Add((byte)(LePlusCourt ^ LePlusLong));

return res;


}

public static ByteArray operator ^(ByteArray B1, byte b)

{

ByteArray res = new ByteArray(B1);

res[res.Count-1] ^= b;

return res;


}

public static ByteArray operator !(ByteArray B1)

{

ByteArray res = new ByteArray();

for(int i = 0;i<B1.Count; ++i)

res.Add((byte)(0xFF - B1));

return res;


}

public static ByteArray operator ~(ByteArray B1)

{

return !B1;

}



#endregion

#region opérateurs de cast

public static implicit operator ByteArray (byte[] source)

{

return new ByteArray(source);

}

public static implicit operator byte[] (ByteArray source)

{

return source.ToArray();

}


#endregion

#region opérateurs de conversion

//public ByteArray (string s) {if (s!=null) foreach (char b in
s.ToCharArray()) {this.Add((byte)b);}}

/// <summary>

/// Converti le ByteArray en byte[]

/// </summary>

/// <returns>un byte[] représentant la liste.</returns>

public byte[] ToArray() { byte[] A = new byte[this.Count];
this.List.CopyTo(A,0); return A; }

/// <summary>

/// renvoie une sous liste du Byte Array sous forme d'un byte[].

/// </summary>

/// <param name="start">L'index de début du sous ByteArray</param>

/// <returns>un byte[] représentant le sous ByteArray</returns>

public byte[] ToArray (int start)

{

/*if (b > e) b = e;

byte[] A = new byte[e-b];

for (int i=b, j=0; i < e; i++, j++)

A[j] = this;

return A;*/

return (new ByteArray(this,start)).ToArray();

}

/// <summary>

/// renvoie une sous liste du Byte Array sous forme d'un byte[].

/// </summary>

/// <param name="b">L'index de début du sous ByteArray</param>

/// <param name="e">la longueur du sous ByteArray</param>

/// <returns>un byte[] représentant le sous ByteArray</returns>

public byte[] ToArray (int start, int len)

{

/*if (b > e) b = e;

byte[] A = new byte[e-b];

for (int i=b, j=0; i < e; i++, j++)

A[j] = this;

return A;*/

return (new ByteArray(this,start,len)).ToArray();

}

/// <summary>

/// constructeur a partir d'une string

/// chaque caractere de la string est convertie en byte

/// si la string est null, renvoie un ByteArray Vide

/// </summary>

/// <param name="s">The string to copy from.</param>

public ByteArray(string Ascii)

{

if(Ascii == null)

return;

byte[] b = (new ASCIIEncoding()).GetBytes(Ascii);

this.Add(b);

}

/// <summary>

/// Converti le ByteArray en une string Hexa avec un séparateur espace (" ")

/// </summary>

/// <returns>une string hexa représentant le ByteArray..</returns>

public string ToHexString() { return ToHexString(" "); }

/// <summary>

/// Converti le ByteArray en une string Hexa avec un séparateur sep.

/// </summary>

/// <param name="sep">La chaine séparatrice entre chauqe byte (paire de
chifre Hexa).</param>

/// <returns>une string hexa représentant le ByteArray.</returns>

public string ToHexString(string sep)

{

StringBuilder SB = new System.Text.StringBuilder();

foreach (byte b in this.List)

SB.AppendFormat(null,"{0:X2}{1}", b, sep);

// supprimer le dernier sep

return SB.ToString().TrimEnd(sep.ToCharArray());

}

/// <summary>

/// Converti le ByteArray en une chaine de caractere, chaque byte étant
converti en un caractère.

/// </summary>

/// <returns>Une string représentant le ByteArray</returns>

public override string ToString()

{

StringBuilder aString = new StringBuilder(this.Count);

foreach(byte b in this)

aString.Append((char)b);

return aString.ToString();

}

/// <summary>

/// Transforme un byteArray en chaine de caractère asccii

/// </summary>

/// <param name="B">Le ByteArray a traduire</param>

/// <returns>une string ascii représentant le byteArray</returns>

public static string ToAscii(ByteArray B)

{

return (new ASCIIEncoding()).GetString(B,0,B.Count);

}


/// <summary>

/// Transforme un byteArray en chaine de caractère asccii

/// </summary>

/// <param name="B">Le ByteArray a traduire</param>

/// <returns>une string ascii représentant le byteArray</returns>

public string ToAscii()

{

return (new ASCIIEncoding()).GetString(this,0,this.Count);

}


/// <summary>

/// Construit un ByteArray à partir d'une chaine de caractère Hexa le
représentant

/// </summary>

/// <param name="Hexa">Une string Hexa représentant le ByteArray</param>

/// <returns>Le ByteArray représenté par la string</returns>

/// <exception cref="FormatException">Le format n'est pas
correct.</exception>

public static ByteArray Parse2(string Hexa)

{

if(Hexa == null || Hexa == "") return new ByteArray();

//string source = Hexa.Replace(" ","").ToUpper();

string source = Hexa.Trim(new char[1]{' '});


if(source.Length % 2 != 0)

source = "0" + source;

ByteArray res = new ByteArray();

for(int i = 0; i<source.Length; i+=2)

{

res.Add(byte.Parse(source.Substring(i,2),System.Globalization.NumberStyles.HexNumber));

}

return res;

}


public static ByteArray Parse(string Hexa)

{

if(Hexa == null || Hexa == "") return new ByteArray();

string source = Hexa.Replace(" ","").ToUpper();

//string source = Hexa.Trim(new char[1]{' '});


if(source.Length % 2 != 0)

source = "0" + source;

ByteArray res = new ByteArray();

for(int i = 0; i<source.Length; i+=2)

{

res.Add(byte.Parse(source.Substring(i,2),System.Globalization.NumberStyles.HexNumber));

}

return res;

}


#endregion


#region MSB LSB

/// <summary>

/// Renvoie le Less significant byte (le dernier de l'array)

/// </summary>

/// <returns></returns>

public byte LSByte()

{

if(this.Count <= 0)throw new IndexOutOfRangeException();

return this[this.Count-1];

}

/// <summary>

/// Renvoie le Most significant byte (le premier de l'array)

/// </summary>

/// <returns></returns>

public byte MSByte()

{

if(this.Count <= 0)throw new IndexOutOfRangeException();

return this[0];

}


#endregion

#region autre opérateurs proche des opérateurs de string

public ByteArray TrimEnd(byte b)

{

ByteArray res = new ByteArray(this);

while(res[res.Count - 1] == b)

res.RemoveAt(res.Count-1);

return res;

}

public ByteArray TrimStart(byte b)

{

ByteArray res = new ByteArray(this);

while(res[0] == b)

res.RemoveAt(0);

return res;

}

public bool EndWith(ByteArray end)

{

if(end == null)

return false;

if(this.Count < end.Count)

return false;

for(int i = 0; i<end.Count; ++i)

{

if(end[end.Count -1 - i] != this[this.Count - 1 - i])

return false;

}

return true;

}

#endregion



}







}
 
Etienne Lebeau said:
Thank you, buy I was looking if the're was a way already implemented in
the framework to do so.

I don't believ there is anything in the framework to do it.
I think I will just wrap the Array in a
ComparableArray class that will overload the Equals() and "==" operator
and implement IComparable. I'm just wondering why this is not already
implemented in the framework due to the fact that it's so low level. Or
maybe I'm just missing something?

I don't think implementing IComparable would work - what would happen
if the array was of a type which didn't implement IComparable itself?

I can't think of any obvious reason why arrays couldn't overload == and
override Equals, although you'd have to be very careful if you had an
object[] which contained a reference to itself as one of its elements.
 
Back
Top