Я нахожусь на стадии разработки, где у меня есть два модуля, и из одного я получил вывод как OutputStream
и второй, который принимает только InputStream
. Вы знаете , как конвертировать OutputStream
в InputStream
( а не наоборот, я имею в виду на самом деле так) , что я буду иметь возможность соединить эти две части?
Спасибо
java
inputstream
outputstream
Точка
источник
источник
new YourOutputStream(thePipedOutputStream)
иnew YourInputStream(thePipedInputStream)
что , вероятно , не так , как ваш поток работ. Поэтому я не думаю, что это решение.Ответы:
Это
OutputStream
тот, где вы пишете данные. Если какой-то модуль предоставляет значениеOutputStream
, ожидается, что на другом конце что-то читается.С
InputStream
другой стороны, что- то, что представляет собой , указывает на то, что вам нужно будет прослушать этот поток, и будут данные, которые вы сможете прочитать.Таким образом, можно подключить
InputStream
кOutputStream
InputStream----read---> intermediateBytes[n] ----write----> OutputStream
Как кто-то упомянул, это то, что позволяет
copy()
метод из IOUtils . Не имеет смысла идти другим путем ... надеюсь, это имеет какой-то смыслОБНОВИТЬ:
Конечно, чем больше я об этом думаю, тем больше я вижу, как это на самом деле будет требованием. Я знаю некоторые комментарии, упомянутые
Piped
потоки ввода / вывода, но есть и другая возможность.Если выходной поток представляет собой
ByteArrayOutputStream
, то вы всегда можете получить полное содержимое, вызвавtoByteArray()
метод. Затем вы можете создать оболочку входного потока с помощьюByteArrayInputStream
подкласса. Эти два псевдопотока, оба они в основном просто заключают массив байтов. Таким образом, использование потоков таким образом технически возможно, но для меня это все еще очень странно ...источник
Кажется, что есть много ссылок и других подобных вещей, но нет реального кода, использующего каналы. Преимущество использования
java.io.PipedInputStream
иjava.io.PipedOutputStream
заключается в том, что нет дополнительного потребления памяти.ByteArrayOutputStream.toByteArray()
возвращает копию исходного буфера, так что это означает, что все, что у вас есть в памяти, теперь у вас есть две его копии. Затем запись вInputStream
средство означает, что теперь у вас есть три копии данных.Код:
Этот код предполагает , что
originalByteArrayOutputStream
это ,ByteArrayOutputStream
как это, как правило , поток использоваться только выход, если вы пишете в файл. Надеюсь, это поможет! Самое замечательное в этом то, что, поскольку он находится в отдельном потоке, он также работает параллельно, поэтому все, что потребляет ваш входной поток, будет также вытекать из вашего старого выходного потока. Это полезно, потому что буфер может оставаться меньше, и у вас будет меньше задержка и меньше использования памяти.источник
out
кin
конструктору, иначе вы могли бы получить исключение закрытого каналаin
из-за состояния гонки (которое я испытал). Используя Java 8 Lambdas:PipedInputStream in = new PipedInputStream(out); ((Runnable)() -> {originalOutputStream.writeTo(out);}).run(); return in;
originalOutputStream
что должно быть правдой, но он не предполагает, как вы управляете своими потоками. Это оставлено на усмотрение разработчика. В этом коде нет ничего, что могло бы вызвать исключение закрытого или разорванного канала.PipedInputStream
Javadocs: говорят, что канал разорван, если поток, который передавал байты данных в подключенный конвейерный поток вывода, больше не существует. Так что я подозреваю, что если вы используете приведенный выше пример, поток завершает работу до того,Jax-RS
как использует входной поток. В то же время я посмотрел на Javadocs MongoDB .GridFSDBFile
имеет входной поток, так почему бы просто не передать его в Jax-RS ?Поскольку потоки ввода и вывода являются только начальной и конечной точкой, решение заключается во временном хранении данных в байтовом массиве. Таким образом, вы должны создать промежуточный продукт
ByteArrayOutputStream
, из которого вы создаете,byte[]
который используется в качестве ввода для новогоByteArrayInputStream
.Надеюсь, поможет.
источник
Вам понадобится промежуточный класс, который будет буфер между. Каждый раз, когда
InputStream.read(byte[]...)
вызывается, класс буферизации будет заполнять переданный байтовый массив следующим портом, переданным изOutputStream.write(byte[]...)
. Поскольку размеры чанков могут не совпадать, класс адаптера должен будет хранить определенное количество до тех пор, пока ему не хватит для заполнения буфера чтения и / или возможности хранения любого переполнения буфера.В этой статье есть несколько разных подходов к этой проблеме:
http://blog.ostermiller.org/convert-java-outputstream-inputstream
источник
источник
toByteArray()
тело метода похоже на это,return Arrays.copyOf(buf, count);
которое возвращает новый массив.Easystream библиотека с открытым исходным кодом имеет прямую поддержку для преобразования OutputStream к InputStream: http://io-tools.sourceforge.net/easystream/tutorial/tutorial.html
Они также перечисляют другие варианты: http://io-tools.sourceforge.net/easystream/OutputStream_to_InputStream.html
источник
Я столкнулся с той же проблемой, связанной с преобразованием a
ByteArrayOutputStream
в a,ByteArrayInputStream
и решил ее с помощью производного класса, изByteArrayOutputStream
которого можно вернуть значениеByteArrayInputStream
, инициализированное внутренним буфером объектаByteArrayOutputStream
. Таким образом, дополнительная память не используется, и «преобразование» происходит очень быстро:Я положил материал на GitHub: https://github.com/nickrussler/ByteArrayInOutStream
источник
Библиотека io-extras может быть полезна. Например, если вы хотите сжать
InputStream
использование,GZIPOutputStream
и вы хотите, чтобы это происходило синхронно (используя размер буфера по умолчанию 8192):Обратите внимание, что библиотека имеет 100% покрытие модульных тестов (что, конечно, стоит!) И находится в Maven Central. Зависимость Maven это:
Обязательно проверьте наличие более поздней версии.
источник
С моей точки зрения, java.io.PipedInputStream / java.io.PipedOutputStream - лучший вариант для рассмотрения. В некоторых ситуациях вы можете использовать ByteArrayInputStream / ByteArrayOutputStream. Проблема в том, что вам нужно продублировать буфер для преобразования ByteArrayOutputStream в ByteArrayInputStream. Также ByteArrayOutpuStream / ByteArrayInputStream ограничены 2 ГБ. Вот реализация OutpuStream / InputStream, которую я написал, чтобы обойти ограничения ByteArrayOutputStream / ByteArrayInputStream (код Scala, но легко понятный для разработчиков Java):
Простота в использовании, нет дублирования буфера, нет 2 ГБ памяти
источник
Если вы хотите создать OutputStream из InputStream, есть одна основная проблема. Запись метода в блоки OutputStream до тех пор, пока это не будет сделано. Таким образом, результат доступен, когда метод записи закончен. Это имеет 2 последствия:
Вариант 1 может быть реализован с использованием байтовых массивов или в виде файла. Вариант 1 может быть реализован с использованием pipies (напрямую или с дополнительной абстракцией - например, RingBuffer или google lib из другого комментария).
Действительно, со стандартным Java нет другого способа решить проблему. Каждое решение является реализацией одного из них.
Существует одна концепция под названием «продолжение» ( подробности см. В Википедии ). В этом случае в основном это означает:
В то время как в некоторых языках эта концепция встроена, для Java нужна некоторая «магия». Например, "commons-javaflow" из apache реализует такое для java. Недостатком является то, что для этого требуются некоторые специальные модификации байт-кода во время сборки. Поэтому было бы разумно поместить все это в дополнительную библиотеку с помощью пользовательских скриптов сборки.
источник
Старый пост, но может помочь другим, используйте этот способ:
источник
toString().getBytes()
в потоке * не вернет содержимое потока.Хотя вы не можете преобразовать OutputStream в InputStream, java предоставляет способ с помощью PipedOutputStream и PipedInputStream, чтобы вы могли записывать данные в PipedOutputStream, чтобы они стали доступны через связанный PipedInputStream.
Некоторое время назад я столкнулся с подобной ситуацией, когда имел дело со сторонними библиотеками, которые требовали, чтобы им был передан экземпляр InputStream вместо экземпляра OutputStream.
Я решил эту проблему, используя PipedInputStream и PipedOutputStream.
Кстати, их сложно использовать, и вы должны использовать многопоточность, чтобы достичь того, что вы хотите. Недавно я опубликовал реализацию на github, которую вы можете использовать.
Вот ссылка . Вы можете пройти через вики, чтобы понять, как его использовать.
источник