Цитировать:
Когда я работал над проектом раньше, я столкнулся с проблемой, то есть картинки, считанные из сети, должны быть загружены в 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.