Сравнить два байтовых массива? (Ява)

96

У меня есть массив байтов с ~ известной двоичной последовательностью в нем. Мне нужно подтвердить, что двоичная последовательность такая, какой она должна быть. Я пробовал .equalsв дополнение ==, но ни один из них не работал.

byte[] array = new BigInteger("1111000011110001", 2).toByteArray();
if (new BigInteger("1111000011110001", 2).toByteArray() == array){
    System.out.println("the same");
} else {
    System.out.println("different'");
}
Роджер
источник
можно просто сравнить строки напрямую?
объекты
1
@objects - ведущие нули. Кроме того, материал String / BigInteger может быть просто способом иллюстрации вопроса сравнения байтовых массивов.
Stephen C
Вы пробовали использовать метод compareTo? Кстати, ==сравнивает примитивные значения просто fyi
ChriskOlson
Вот связанный с этим вопрос о сравнении частичных массивов: stackoverflow.com/questions/16646967/…
Вадзим

Ответы:

167

В вашем примере у вас есть:

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

При работе с объектами ==в java сравниваются справочные значения . Вы проверяете, toByteArray()совпадает ли ссылка на массив, возвращаемый с помощью, со ссылкой, содержащейся в нем array, что, конечно, никогда не может быть правдой. Кроме того, классы массивов не переопределяют, .equals()поэтому поведение таково, Object.equals()что также сравниваются только справочные значения.

Для сравнения содержимого двух массивов классом 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!");
}
Брайан Роуч
источник
64

Ознакомьтесь с семейством статических java.util.Arrays.equals()методов. Есть тот, который делает именно то, что вы хотите.

Эрнест Фридман-Хилл
источник
11

Java не перегружает операторы, поэтому обычно вам понадобится метод для неосновных типов. Попробуйте метод Arrays.equals () .

jswolf19
источник
11

Вы можете использовать как Arrays.equals()и MessageDigest.isEqual(). Однако у этих двух методов есть некоторые различия.

MessageDigest.isEqual()- это метод сравнения с постоянной Arrays.equals()времени, он не является постоянным по времени и может вызвать некоторые проблемы с безопасностью, если вы используете его в приложении безопасности.

Подробнее о различиях можно прочитать в Arrays.equals () vs MessageDigest.isEqual ()

PixelsTech
источник
3

Конечно, принятый ответ Arrays.equal (сначала байт [], затем байт []) правильный. Мне нравится работать на более низком уровне, но мне не удалось найти эффективную функцию низкого уровня для выполнения диапазонов проверки равенства. Пришлось сколотить свой, если кому нужно:

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;
}
Бамако
источник
Это хорошее решение для тестирования подмножества массивов, а не целого. Однако обратите внимание, что Arrays.equals (byte [], byte []) делает почти то же самое, что и вы здесь (за исключением более эффективной обработки двух значений, являющихся одним и тем же объектом, и обработки нулевых массивов, передаваемых изящно). Когда мне предоставляется выбор: использовать стандартную реализацию библиотеки, которая будет поддерживаться сообществом, или написать ее собственную реализацию, которую мне нужно поддерживать вечно, я каждый раз выбираю первое.
Том Диббл,
4
Ответ полезен для случая использования, когда у одного есть два массива и вы хотите сравнить диапазон байтов из них, без предварительного создания копий массивов. Копии массивов увеличивают накладные расходы, добавляют мусор и не нужны. Мне нужна была функция memcmp () в стиле c низкого уровня, и это соответствовало потребностям. Конечно, memcmp () принимает только один аргумент длины. Эта функция достаточно близка.
Бамако,
2

Поскольку я хотел сравнить два массива для модульного теста и пришел к этому ответу, я подумал, что могу поделиться.

Вы также можете сделать это с помощью:

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

  Assert.assertArrayEquals(array, secondArray);
}

И вы можете проверить Сравнение массивов в утверждениях JUnit для получения дополнительной информации.

Sylhare
источник