Comparer deux tableaux d'octets? (Java)

96

J'ai un tableau d'octets avec une séquence binaire connue. Je dois confirmer que la séquence binaire est ce qu'elle est censée être. J'ai essayé .equalsen plus ==, mais aucun n'a fonctionné.

byte[] array = new BigInteger("1111000011110001", 2).toByteArray();
if (new BigInteger("1111000011110001", 2).toByteArray() == array){
    System.out.println("the same");
} else {
    System.out.println("different'");
}
Roger
la source
pouvez-vous simplement comparer les chaînes directement?
objets du
1
@objects - zéros non significatifs. En outre, le truc String / BigInteger pourrait simplement être un moyen d'illustrer la question de comparaison de tableau d'octets.
Stephen C
Avez-vous essayé d'utiliser la méthode compareTo? BTW ==compare les valeurs primitives juste pour fyi
ChriskOlson
Voici une question connexe sur la comparaison de tableaux partiels: stackoverflow.com/questions/16646967/…
Vadzim

Réponses:

165

Dans votre exemple, vous avez:

if (new BigInteger("1111000011110001", 2).toByteArray() == array)

Lorsqu'il s'agit d'objets, ==en java compare les valeurs de référence . Vous vérifiez si la référence au tableau renvoyé par toByteArray()est la même que la référence contenue dans array, ce qui bien sûr ne peut jamais être vrai. De plus, les classes de tableaux ne remplacent pas, .equals()donc le comportement est celui Object.equals()dont ne compare également que les valeurs de référence.

Pour comparer le contenu de deux tableaux, des méthodes de comparaison de tableaux statiques sont fournies par la classe Arrays

byte[] array = new BigInteger("1111000011110001", 2).toByteArray();
byte[] secondArray = new BigInteger("1111000011110001", 2).toByteArray();
if (Arrays.equals(array, secondArray))
{
    System.out.println("Yup, they're the same!");
}
Brian Roach
la source
64

Découvrez la java.util.Arrays.equals()famille de méthodes statiques . Il y en a un qui fait exactement ce que vous voulez.

Ernest Friedman-Hill
la source
11

Java ne surcharge pas les opérateurs, vous aurez donc généralement besoin d'une méthode pour les types non basiques. Essayez la méthode Arrays.equals () .

jswolf19
la source
11

Vous pouvez utiliser à la fois Arrays.equals()et MessageDigest.isEqual(). Ces deux méthodes présentent cependant quelques différences.

MessageDigest.isEqual()est une méthode de comparaison à constante de temps et Arrays.equals()n'est pas constante de temps et peut entraîner des problèmes de sécurité si vous l'utilisez dans une application de sécurité.

Les détails de la différence peuvent être lus sur Arrays.equals () vs MessageDigest.isEqual ()

PixelsTech
la source
3

Bien sûr, la réponse acceptée de Arrays.equal (byte [] first, byte [] second) est correcte. J'aime travailler à un niveau inférieur, mais je n'ai pas pu trouver une fonction efficace de bas niveau pour effectuer des plages de test d'égalité. Je devais créer le mien, si quelqu'un en avait besoin:

public static boolean ArraysAreEquals(
 byte[] first,
 int firstOffset,
 int firstLength,
 byte[] second,
 int secondOffset,
 int secondLength
) {
    if( firstLength != secondLength ) {
        return false;
    }

    for( int index = 0; index < firstLength; ++index ) {
        if( first[firstOffset+index] != second[secondOffset+index]) {
            return false;
        }
    }

    return true;
}
Bamaco
la source
C'est une bonne solution pour tester un sous-ensemble de tableaux plutôt que le tout. Cependant, notez que Arrays.equals (byte [], byte []) fait à peu près exactement tout ce que vous avez fait ici (sauf gère les deux valeurs étant le même objet plus efficacement et gère les tableaux nuls passés gracieusement). Lorsqu'on me donne le choix d'utiliser une implémentation de bibliothèque standard qui sera prise en charge par la communauté ou d'écrire une implémentation personnalisée de celle-ci que je devrai supporter pour toujours, je choisirai la première à chaque fois.
Tom Dibble
4
La réponse est utile pour le cas d'utilisation où l'on a deux tableaux et que l'on souhaite comparer une plage d'octets à partir d'eux, sans faire de copie préalable des tableaux. Les copies de tableau ajoutent une surcharge, ajoutent des déchets et ne sont pas nécessaires. Ce dont j'avais besoin, c'était un memcmp () de style c de bas niveau et cela correspond au besoin. Bien sûr, memcmp () ne prend qu'un seul argument de longueur. Cette fonction est assez proche.
Bamaco
2

Puisque je voulais comparer deux tableaux pour un test unitaire et que je suis arrivé sur cette réponse, je pensais pouvoir partager.

Vous pouvez également le faire avec:

@Test
public void testTwoArrays() {
  byte[] array = new BigInteger("1111000011110001", 2).toByteArray();
  byte[] secondArray = new BigInteger("1111000011110001", 2).toByteArray();

  Assert.assertArrayEquals(array, secondArray);
}

Et vous pouvez consulter Comparaison des tableaux dans les assertions JUnit pour plus d'informations.

Sylhare
la source