2009-09-07 126 views
11

我有使用.NET 3.0 C#中两个字节数组。C#字节数组比较

什么是“最有效”的方式来比较两个字节数组是否包含每个元素的相同的内容?

例如,字节数组{0x1, 0x2}相同{0x1, 0x2}。但是字节数组{0x1, 0x2}和字节数组{0x2, 0x1}是不一样的。

+2

重复的http://stackoverflow.com/questions/43289/ – Hafthor 2010-04-02 18:44:55

回答

32

嗯,你可以使用:

public static bool ByteArraysEqual(byte[] b1, byte[] b2) 
{ 
    if (b1 == b2) return true; 
    if (b1 == null || b2 == null) return false; 
    if (b1.Length != b2.Length) return false; 
    for (int i=0; i < b1.Length; i++) 
    { 
     if (b1[i] != b2[i]) return false; 
    } 
    return true; 
} 

(我通常使用大括号的一切,但我想我会用这个布局风格实验只是为了改变...)

这有一些SequenceEqual不能(或不)执行的优化 - 例如前期长度检查。直接数组访问也比使用枚举器更高效。

诚然这是不太可能在大多数情况下,显著差异...

你可以可能通过使其在一个时间,而不是8比32或64位,使其更快非托管代码 - 但我不想在飞行中编码。

+0

我喜欢你的解决方案! – George2 2009-09-07 14:13:41

+0

嘿乔恩,你是否为stackoverflow工作? – Shiva 2009-09-08 01:22:54

+2

@Shiva:不,我为Google工作 – 2009-09-08 05:19:13

24

可以使用SequenceEqual方法:

bool areEqual = firstArray.SequenceEqual(secondArray); 

正如评论所说,SequenceEqual需要.NET 3.5(或LINQBridge如果你使用VS2008和定位框架的早期版本)。

+1

我认为最有效的方式。 – 2009-09-07 14:05:55

+1

不是在执行时间方面,它不是。 – 2009-09-07 14:07:22

+1

@Veton:这当然是最少输入的!请参阅乔恩的答案进行一些额外的优化。 – LukeH 2009-09-07 14:07:26

3

如果你希望它是真快,你可以使用不安全的代码(这并不总是可能):

public static bool ArraysEqual(byte[] b1, byte[] b2) 
    { 
     unsafe 
     { 
      if (b1.Length != b2.Length) 
       return false; 

      int n = b1.Length; 

      fixed (byte *p1 = b1, p2 = b2) 
      { 
       byte *ptr1 = p1; 
       byte *ptr2 = p2; 

       while (n-- > 0) 
       { 
        if (*ptr1++ != *ptr2++) 
         return false; 
       } 
      } 

      return true; 
     } 
    } 
5

乔恩提到一次使用不安全的代码比较多个字节,所以我不得不放弃它一去:

public unsafe bool ByteArraysEqual(byte[] b1, byte[] b2) { 
    if (b1 == b2) return true; 
    if (b1 == null || b2 == null) return false; 
    if (b1.Length != b2.Length) return false; 
    int len = b1.Length; 
    fixed (byte* p1 = b1, p2 = b2) { 
     int* i1 = (int*)p1; 
     int* i2 = (int*)p2; 
     while (len >= 4) { 
     if (*i1 != *i2) return false; 
     i1++; 
     i2++; 
     len -= 4; 
     } 
     byte* c1 = (byte*)i1; 
     byte* c2 = (byte*)i2; 
     while (len > 0) { 
     if (*c1 != *c2) return false; 
     c1++; 
     c2++; 
     len--; 
     } 
    } 
    return true; 
} 

的安全代码被漂亮优化(编译器知道它没有检查例如指数边界),所以我不希望在不安全的代码是非常快的多。任何显着差异都会来自一次比较几个字节的能力。

+0

好的概念,虽然代码不能编译:“Can not分配给'p1',因为它是'固定变量'“ – 2011-03-16 03:56:06

+0

@Edward Brey:你说得对,这是行不通的,你需要在块内声明新的指针以使它们可以改变,我已经更正了代码 – Guffa 2011-03-16 05:56:12

+0

即使在32位计算机上,使用long(8字节)的速度也会更快。 – Joe 2011-07-28 14:50:01

2

如果您不太在意性能,可以考虑IStructuralEquatable

.NET框架支持:4.5,4

结构相等的意思是两个对象相等,因为它们具有相同的值。它与参考平等不同。

实施例:

static bool ByteArrayCompare(byte[] a1, byte[] a2) 
{ 
    IStructuralEquatable eqa1 = a1; 
    return eqa1.Equals(a2, StructuralComparisons.StructuralEqualityComparer); 
} 

REFERENCE

  1. What problem does IStructuralEquatable and IStructuralComparable solve?
  2. Why aren't IStructuralEquatable and IStructuralComparable generic?
  3. IStructuralEquatable Interface
+1

给这篇文章提一点:当我们使用最新版本的框架时,这可能是一种做事情的方式。 – timmi4sa 2013-08-14 00:25:30