Есть ли краткий способ создать InputSupplier для InputStream в Google Guava?
Вопрос
В Google Guava есть несколько фабричных методов для создания InputSuppliers, например.из byte[]
:
ByteStreams.newInputStreamSupplier(bytes);
Или из File
:
Files.newInputStreamSupplier(file);
Есть ли аналогичный способ создания InputSupplier
для данного InputStream
?
То есть более краткий способ, чем анонимный класс:
new InputSupplier<InputStream>() {
public InputStream getInput() throws IOException {
return inputStream;
}
};
Фон:Я хотел бы использовать InputStreams, например. Files.copy(...)
или ByteStreams.equal(...)
.
Решение
Нет, я ничего не видел.
Я думаю, вы нашли лучший способ.
Единственная альтернатива: сохранить входной поток в массиве байтов или файле и создать поставщика с помощью ByteStreams.newInputStreamSupplier() или Files.newInputStreamSupplier(), но я бы не советовал это делать.
Вы также можете использовать
public static long copy(InputStream from, OutputStream to)
от ByteStreams
видеть:источник
Другие советы
Невозможно преобразовать произвольный InputStream
в InputSupplier<InputStream>
, потому что InputSupplier<InputStream>
Предполагается, что это объект, который может создать свежий, новый InputStream
каждый раз, когда это getInput()
метод называется.Это возможно только в том случае, если базовый источник байтов доступен для повторного использования;отсюда и фабричные методы, которые принимают byte[]
или File
и вернуть InputSupplier<InputStream>
.
Как предполагает Димитрис, InputSupplier
имеет отношение к InputStream
таким же образом, что Iterable
имеет отношение к Iterator
.Описываемый вами анонимный класс неверен, поскольку он возвращает такой же транслировать каждый раз getInput()
вызывается, поэтому последующие вызовы будут возвращать InputStream
который уже исчерпан и закрыт.
Вот еще одна проблема с вашим анонимным классом:часть мотивации InputSupplier
заключается в ограничении видимости фактического InputStream
чтобы его можно было закрыть автоматически.Если вы обернете внешне видимый InputStream
в InputSupplier
а затем передать это в служебный метод, служебный метод может закрыть ваш InputStream
.Возможно, вас это устраивает, но это не тот шаблон использования, который Guava хотела бы продвигать.
Когда я обнаружил, что хочу сделать то же самое, я понял, что делаю это наоборот.Вместо этого:
Files.copy(InputSupplier.of(inputStream), destinationFile);
(не существует), вместо этого я должен сделать это:
ByteStreams.copy(inputStream, Files.newOutputStreamSupplier(destinationFile));
Это было бы так же неправильно, как обертывание Iterator в Iterable. Я считаю, что вероятность попадания такой вещи в библиотеку равна нулю.Как говорит Элу, вы можете использовать метод ByteStreams.copy(), но, похоже, нет очевидной причины использовать метод равенства() для двух потоков.
Я понимаю, что авторы гуавы не решаются добавить такой (тривиальный) метод - насколько часто он может полностью (или частично, но без знания того, где остался поток, так что после этого его практически невозможно использовать) читать два потока, просто чтобы посмотреть, есть ли они одинаковы, без какой-либо другой обработки данных?Поступают ли эти байты из неповторяемого источника чтения, например сетевого сокета?В противном случае, если это где-то просто файл или массив байтов в памяти, есть другие способы, которые позволяют провести проверку на равенство.