Comparing two byte arrays in .NET
Edit: modern fast way is to use a1.SequenceEquals(a2)
User gil suggested unsafe code which spawned this solution:
// Copyright (c) 2008-2013 Hafthor Stefansson
// Distributed under the MIT/X11 software license
// Ref: http://www.opensource.org/licenses/mit-license.php.
static unsafe bool UnsafeCompare(byte[] a1, byte[] a2) {
unchecked {
if(a1==a2) return true;
if(a1==null || a2==null || a1.Length!=a2.Length)
return false;
fixed (byte* p1=a1, p2=a2) {
byte* x1=p1, x2=p2;
int l = a1.Length;
for (int i=0; i < l/8; i++, x1+=8, x2+=8)
if (*((long*)x1) != *((long*)x2)) return false;
if ((l & 4)!=0) { if (*((int*)x1)!=*((int*)x2)) return false; x1+=4; x2+=4; }
if ((l & 2)!=0) { if (*((short*)x1)!=*((short*)x2)) return false; x1+=2; x2+=2; }
if ((l & 1)!=0) if (*((byte*)x1) != *((byte*)x2)) return false;
return true;
}
}
}
which does 64-bit based comparison for as much of the array as possible. This kind of counts on the fact that the arrays start qword aligned. It'll work if not qword aligned, just not as fast as if it were.
It performs about seven timers faster than the simple `for` loop. Using the J# library performed equivalently to the original `for` loop. Using .SequenceEqual runs around seven times slower; I think just because it is using IEnumerator.MoveNext. I imagine LINQ-based solutions being at least that slow or worse.
Checking equality for two byte arrays
You need to add a return value somewhere. This should work:
public bool Equality(byte[] a1, byte[] b1)
{
int i;
if (a1.Length == b1.Length)
{
i = 0;
while (i < a1.Length && (a1[i]==b1[i])) //Earlier it was a1[i]!=b1[i]
{
i++;
}
if (i == a1.Length)
{
return true;
}
}
return false;
}
But this is much simpler:
return a1.SequenceEqual(b1);
Alternatively, you could use IStructuralEquatable
from .NET 4:
return ((IStructuralEquatable)a1).Equals(b1, StructuralComparisons.StructuralEqualityComparer)
If performance is a concern, I'd recommend rewriting your code to use the Binary
class, which is specifically optimized for this kind of use case:
public bool Equality(Binary a1, Binary b1)
{
return a1.Equals(b1);
}
A quick benchmark on my machine gives the following stats:
Method Min Max Avg
binary equal: 0.868 3.076 0.933 (best)
for loop: 2.636 10.004 3.065
sequence equal: 8.940 30.124 10.258
structure equal: 155.644 381.052 170.693
Download this LINQPad file to run the benchmark yourself.
How to compare two arrays of bytes
Try using the SequenceEqual
extension method. For example:
byte[] a1 = new byte[] { 1, 2, 3 };
byte[] a2 = new byte[] { 1, 2, 3 };
bool areEqual = a1.SequenceEqual(a2); // true
C# - byte array - byte[] - Is there a simple comparer?
You are looking for SequenceEqual
method.
a.SequenceEqual(b);
Determines whether two sequences are equal by comparing the elements by using the default equality comparer for their type.
Comparing 2 hashed byte arrays
Basically, if you only have the byte hash in DB, you want to compare two byte array ?
You can get this here: Comparing two byte arrays in .NET
One of the options that might work for you is:
StructuralComparisons.StructuralEqualityComparer.Equals(hashedBytes,
previousHashedBytes)
How do i compare byte arrays in vb.net
Use SequenceEqual
Dim foo() As Byte = {1, 2, 3, 4}
Dim barT() As Byte = {1, 2, 3, 4}
Dim barF() As Byte = {1, 2, 3, 5}
Dim fooEqbarT As Boolean = foo.SequenceEqual(barT)
Dim fooEqbarF As Boolean = foo.SequenceEqual(barF)
Debug.WriteLine(fooEqbarT)
Debug.WriteLine(fooEqbarF)
Compare two small files
Dim path1 As String = "pathnameoffirstfile"
Dim path2 As String = "pathnameofsecondfile"
Dim foo() As Byte = IO.File.ReadAllBytes(path1)
Dim bar() As Byte = IO.File.ReadAllBytes(path2)
If foo.SequenceEqual(bar) Then
'identical
Else
'different
End If
C# Compare two byte[] arrays containing text as lowercase
Lowercase and uppercase ACSII and UTF8 code's byte representation have an offset of 32 (or hex20), so you can implement a comparison of x == byte[x] || x == byte[x+32]
with x=uppercase char value.
edit:
suppose you really have to deal only with small and capital english letters, you can hack around with bitwise operations to speed things up, as you can handle 8 byte / chars at once, because those only differ by the 3rd most significant bit:
'b' & 0b_1101_1111 == 'B' & 0b_1101_1111
so you could handle the byte array in 8 byte chunks:
void Main()
{
byte[] a = "ASDADAGF".Select(x => (byte)(x) ).ToArray();
byte[] b = "asdAdAGF".Select(x => (byte)(x) ).ToArray();
bitCompared(a,b).Dump();
}
static bool bitCompared( byte[] b1, byte[]b2)
{
UInt64 a = BitConverter.ToUInt64(b1, 0); //loop over the index
UInt64 b = BitConverter.ToUInt64(b2, 0);
UInt64 mask =0b_1101_1111_1101_1111_1101_1111_1101_1111_1101_1111_1101_1111_1101_1111_1101_1111;
return (a &= mask) == (b &= mask);
}
afaik there are also even more ways to optimize with SIMD and other low level "hacks".....
Comparing two Byte Arrays byte by byte and return there difference?
If you just want a count of the number of differences try this
byte[] array1 = new byte[2];
byte[] array2 = new byte[2];
int diff = array1.Where((x, i) => x != array2[i]).Count();
How to compare two byte arrays with greater than or less than operator value in C# or Linq?
One way is to use IStructuralComparable
, which Array
implicitly implements:
byte[] rv1 = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01 };
byte[] rv2 = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x05 };
var result = ((IStructuralComparable)rv1).CompareTo(rv2, Comparer<byte>.Default); // returns negative value, because rv1 < rv2
If for some reason you want to use BitConverter
, you have to reverse arrays, because BitConverter
is little endian on most architectures (to be safe - you should check BitConverter.IsLittleEndian
field and reverse only if it returns true). Note that it's not very efficient to do this.
var i1 = BitConverter.ToUInt64(rv1.Reverse().ToArray(), 0);
var i2 = BitConverter.ToUInt64(rv2.Reverse().ToArray(), 0);
Now if you use Entity Framework and need to compare timestamps in database query, situation is a bit different, because Entity Framework will inspect your query expression looking for patterns it understands. It does not understand IStructuralComparable
comparisions (and BitConverter
conversions too of course), so you have to use a trick. Declare extension method for byte array with the name Compare
:
static class ArrayExtensions {
public static int Compare(this byte[] b1, byte[] b2) {
// you can as well just throw NotImplementedException here, EF will not call this method directly
if (b1 == null && b2 == null)
return 0;
else if (b1 == null)
return -1;
else if (b2 == null)
return 1;
return ((IStructuralComparable) b1).CompareTo(b2, Comparer<byte>.Default);
}
}
And use that in EF LINQ query:
var result = ctx.TestTables.Where(c => c.RowVersion.Compare(rv1) > 0).ToList();
When analyzing, EF will see method with name Compare
and compatible signature and will translate that into correct sql query (select * from Table where RowVersion > @yourVersion)
c# compare byte arrays
As other comments have already stated, the problem is that you are comparing pointers, not values. The correct code should be:
if (*(intfirst + i) != *(intsecond + i))
But I'd like to point out a deeper issues in your code.
If the input
byte
arrays have lengths that don't align with4
(first.Length % 4 != 0
) you will get false positives because you'll
be essentially swallowing all misaligned items:{1, 2, 3, 4, 5}
{1, 2, 3, 4, 7}Will return
true
when they are obviously not the same.You should be checking, before anything else, that both
arrays have the same length and bailing out fast if they don't. You'll
run into all kind of issues otherwise.{1, 2, 3, 0}
{1, 2, 3}Will also return
true
when it shoudn't.
Related Topics
How to Get the Current Username in .Net Using C#
Why Do I Get "'Property Cannot Be Assigned" When Sending an Smtp Email
C# Convert Int to String With Padding Zeros
How to Convert a C# String Value to an Escaped String Literal
Color Different Parts of a Richtextbox String
What Is the Simplest Method of Inter-Process Communication Between 2 C# Processes
How to Replace Multiple Spaces With a Single Space in C#
.Net Global Exception Handler in Console Application
How to Update an Observablecollection Via a Worker Thread
How to Load Image to Wpf in Runtime
Why Doesn't C# Infer My Generic Types
How to Create and Connect Custom User Buttons/Controls With Lines Using Windows Forms
Detect If Deserialized Object Is Missing a Field With the Jsonconvert Class in Json.Net
Picturebox Paintevent With Other Method
What Is the { Get; Set; } Syntax in C#
How to Automatically Increment the File Build Version When Using Visual Studio