Как повторно использовать inputStream?

Java

Цитировать:

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

анализ проблемы:

Внутри inputStream есть указатель pos. При чтении указатель будет двигаться непрерывно. Когда он дойдет до конца, его нельзя прочитать снова. Давайте напишем простой пример, чтобы увидеть:

    String text = "测试inputStream内容";
    InputStream inputStream = new ByteArrayInputStream(text.getBytes());
    byte[] readArray = new byte[inputStream.available()];
    int readCount1 = inputStream.read(readArray);
    System.out.println("读取了" + readCount1 + "个字节");

    byte[] readArray2 = new byte[inputStream.available()];
    int readCount2 = inputStream.read(readArray2);
    System.out.println("读取了" + readCount2 + "个字节");
    /**
    *  执行结果是
    *  读取了23个字节
    *  读取了-1个字节
    */

Из результатов выполнения видно, что дизайн входного потока можно прочитать только один раз.Примечание: здесь упоминается метод inputStream.available().Локальный файл может напрямую знать размер файла, но если это данные в сети, лучше не использовать этот метод, потому что передача не является непрерывной и размер данных будет неточным для чтения.

проблема решена:

Итак, как мы должны решить это в нашем реальном проекте? Вы не можете просто использовать inputSteam один раз. Посмотрим на решение:метод первый: Используйте ByteArrayOutputStream для буферизации байтов, а затем выполняйте каждое чтение из буферизованного ByteArrayOutputStream. Мы, естественно, думаем о кэшировании inputStream (конечно, это не обязательно означает, что он должен быть помещен в ByteArrayOutputStream. Возможны и другие способы. Все они являются идеями кэширования. Есть много способов добиться этого, что более удобно. )

       String text = "测试inputStream内容";
       InputStream rawInputStream = new ByteArrayInputStream(text.getBytes());
       ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
       byte[] buffer = new byte[1024];
       int len;
       while ((len = rawInputStream.read(buffer)) > -1) {
           outputStream.write(buffer, 0, len);
       }
       outputStream.flush();
       InputStream in1 = new ByteArrayInputStream(outputStream.toByteArray());
       InputStream in2 = new ByteArrayInputStream(outputStream.toByteArray());
       int readCount1 = in1.read(buffer);
       int readCount2 = in2.read(buffer);
       System.out.println("读取了" + readCount1 + "个字节");
       System.out.println("读取了" + readCount2 + "个字节");
       /**
       *  执行结果是
       *  读取了23个字节
       *  读取了23个字节
       *

Здесь нужно прочитать данные InputStream в OUTPUT, затем использовать содержимое inputStream, мы вынимаем данные в Output (очень волшебная настройка, Output можно повторить, INPUT можно прочитать только один раз)

Способ второй:
На самом деле, есть методы для работы с указателями в inputStream, mark и reset, по названию можно сказать, что это mark и reset. Перед использованием inputSteam мы помечаем положение указателя inputStream, прочитав его, сбрасываем, и тогда его можно использовать повторно. Давайте посмотрим на код:

      String text = "测试inputStream内容";
      InputStream rawInputStream = new ByteArrayInputStream(text.getBytes());
      byte[] readArray = new byte[1024];
      rawInputStream.mark(0);
      int readCount1 = rawInputStream.read(readArray);
      rawInputStream.reset();
      int readCount2 = rawInputStream.read(readArray);
      System.out.println("读取了" + readCount1 + "个字节");
      System.out.println("读取了" + readCount2 + "个字节");

Суммировать:

1. inputStream можно прочитать только один раз, то есть метод read() или другой метод read() с параметрами можно вызвать только один раз, при следующем вызове read будет -1. забудьте об этом, когда вы работаете над проектом, это может привести к появлению ям; 2. Вы можете использовать метод cache или mark/reset для повторного использования inputStream.Здесь следует отметить, что если inputStream имеет много контента, кеширование не является хорошим способом, потому что он будет занимать много памяти перед он израсходован (я сталкивался с этим, после загрузки много картинок и тут кеш, памяти не хватает и фулгк всегда полный, а то сначала рвется цп); 3. Еще один небольшой момент: не забудьте закрыть используемый inputStream/outputSteam.