Как сравнить содержимое двух объектов InputStreams

Я хочу сравнить содержимое в cis и resStream. Моя цель - проверить, дало ли мне повторное шифрование те же данные или разные.

Любые зацепки были бы действительно замечательными. Спасибо

final InputStream cis = test.getEncryptingInputStream(is);
final InputStream resStream = test.reEncrypt(cis, "");

Как мы можем проверить содержимое InputStreams?

InputStream имеет read метод. Начните с этого, попробуйте реализовать, а если застрянете, задайте новый вопрос с конкретными деталями.
Jorn 25.07.2023 13:42

Вызовите read() для каждого и прекратите чтение, как только два вызова дадут разные значения. Вы можете сократить путь, вернув false, если файлы (если они файлы) различаются по длине.

g00se 25.07.2023 13:49

Читать весь поток, md5 его, если хеши разные - контент другой.

Shark 25.07.2023 13:58
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
3
50
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Как сравнить содержимое 2 InputStreams объектов?

Вы можете прочитать данные из каждого потока и сравнить их байтовые коды. Не то, чтобы если потоки имеют разный размер, то они определенно не равны.

int cisByte = cis.read();
int resByte = resStream.read();

while (cisByte != -1 && resByte != -1) {
    if (cisByte != resByte) {
        return false;
    }
    cisByte = cis.read();
    resByte = resStream.read();
}

return cisByte == resByte;

Я уверен, что test.reEncrypt(cis, "") уже читал бы стрим cis внутри него. Вот как это вернет reStream. Таким образом, вышеуказанная функция для чтения обоих одновременно не будет работать. Когда вы читаете из resStream для внутреннего шифрования байта, он также будет считываться из cis. Таким образом, из cis будет прочитано 2 байта (один с помощью вышеуказанной функции и один с помощью resStream.read() внутри), а из resByte только один. Зависит от того, как работает алгоритм. Но это в основном не сработает.

Ishan 25.07.2023 13:59

Есть ли способ преобразовать содержимое в inputStream в строку, чтобы я мог сравнить обе строки, если они равны или нет.

priyanka 25.07.2023 14:27

@priyanka Да, вы можете использовать «BufferedReader». Что-то вроде "BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));" и 'Построитель StringBuilder = новый StringBuilder();' затем поместите билдер в плавленный цикл, например, while, и вызовите «добавить», не стесняйтесь задавать другой вопрос об этом, если вам нужна дополнительная информация об этом.

Lunatic 25.07.2023 14:30

Спасибо всем за быстрые ответы.

priyanka 25.07.2023 14:45

Если у вас есть два файла, то boolean identical = (Files.mismatch(path1, path2) == -1);

g00se 25.07.2023 15:02

Apache Commons IO имеет этот метод: commons.apache.org/proper/commons-io/apidocs/org/apache/comm‌​ons/…

Rob Spoor 25.07.2023 16:49
Ответ принят как подходящий

Идея состоит в том, чтобы прочитать весь поток как строку, затем md5 строку и, наконец, проверить, совпадают ли хэши. MD5 гарантирует, что хеширование одной и той же строки даст тот же результат.

public String readInputStreamAsString(InputStream stream) {
 int bufferSize = 1024;
 char[] buffer = new char[bufferSize];
 StringBuilder out = new StringBuilder();
 Reader in = new InputStreamReader(stream, StandardCharsets.UTF_8);
 for (int numRead; (numRead = in.read(buffer, 0, buffer.length)) > 0; ) {
     out.append(buffer, 0, numRead);
 }
 return out.toString();
}

public String hashMD5(String input) {
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] messageDigest = md.digest(input.getBytes());
        BigInteger number = new BigInteger(1, messageDigest);
        String hashtext = number.toString(16);
        return hashtext;
}

public void TestMe() {
   final InputStream cis = test.getEncryptingInputStream(is);
   final InputStream resStream = test.reEncrypt(cis, "");

   String cisAsString = readInputStreamAsString(cis);
   String resStreamAsString = readInputStreamAsString(resStream);

   String cisMD5 = hashMD5(cisAsString);
   String resMD5 = hashMD5(resStreamAsString);

   if (cisMD5.equals(resMD5)) { 
       System.out.println("Streams contents are equal"); 
   } else { 
       System.out.println("Stream contents are NOT equal :("); 
   }
}

Конечно, быстрее просто сравнить две строки, чем вычислять хэш, а затем сравнивать хэш? И тогда нет никаких шансов, что две разные строки хешируют одно и то же значение.

tgdavies 25.07.2023 14:08

Для бесконечно длинной строки - конечно, сравнение отдельных символов - это путь. Для 10 мегабайт тестовых данных - есть ли разница? Я думал, что весь смысл вопроса в том, чтобы определить, есть ли разница, а не где она. Идентичные строки обязательно будут хэшироваться до одного и того же значения. Разные строки (следовательно, разное содержимое) не будут хешироваться до одного и того же значения.

Shark 25.07.2023 14:11

@tgdavies смотри: My target is to check if the reEncryption gave me the same data or different.. Это делает это просто отлично. Возможно, неоптимальным способом, но простым способом.

Shark 25.07.2023 14:12

Вы сделали решение более медленным, менее надежным и более сложным без какой-либо выгоды. Выражение cisMD5.equals(resMD5) может быть просто cisAsString.equals(resStreamAsString)

tgdavies 25.07.2023 14:12

@tgdavies Надежность в стороне, разве это не демонстрирует идею сравнения двух вещей? Улучшение и оптимизация оставлены читателю в качестве упражнения :) Что, вероятно, для начала пропустит все чтение в строку.

Shark 25.07.2023 14:19

Кто сказал что-нибудь о Strings?

g00se 25.07.2023 14:56

Это приведет к сравнению с потерями, поскольку не все комбинации байтов допустимы в UTF-8 и приводят к замене символов Unicode (не говоря уже о том, что неквалифицированное использование String.getBytes() также может привести к потерям, если набор символов JVM по умолчанию не UTF-8), поэтому два разных потока могут создавать одну и ту же строку. Если вы хотите определить хэш, используйте DigestInputStream и прочитайте его (отбрасывая байты).

Mark Rotteveel 25.07.2023 14:58

Ставлю только алгоритм, а не реальную реализацию...

final InputStream cis = test.getEncryptingInputStream(is);
Create a ByteArrayOutputStream cisArray / FileOutputStream
Read everything from cis and store in cisArray/FileOutputStream.

Create cisInputStream as ByteArrayInputStream from stored cisArray's bytes OR FileInputStream from file.
final InputStream resStream = test.reEncrypt(cisInputStream, "");

Read resStream & cisInputStream (re-open) byte by byte and compare

Зачем тебе все читать в память?

g00se 25.07.2023 14:54

По крайней мере, один поток - cis должен быть прочитан в память и сохранен для последующего сравнения с выводом reEncrypt. Чтение resStream может выполняться побайтно и сравниваться с cisArray. Но, по крайней мере, cisArray нужно прочитать полностью и запомнить.

Ishan 25.07.2023 15:14

И зависит, вывод test.getEncryptingInputStream(is) тоже можно сохранить в файл, если памяти слишком много. Суть в том, что мы должны полностью прочитать один поток и где-то сохранить, а затем создать другой поток из этих сохраненных данных (в памяти или на диске) и передать его функции reEncrypt. Если мы напрямую передадим вывод getEncryptingInputStream в reEncrypt, это не сработает. Вы не можете прочитать первый вывод дважды. Вывод reEncrypt не нужно нигде хранить, а просто сравнить с сохраненным выводом getEncryptingInputStream

Ishan 25.07.2023 15:22

Другие вопросы по теме