Jestem na etapie rozwoju, gdzie mam dwa moduły i z jednego dostałem wyjście jako OutputStream
drugi i drugi, który akceptuje tylko InputStream
. Czy wiesz, jak przekonwertować OutputStream
na InputStream
(nie odwrotnie, mam na myśli naprawdę w ten sposób), że będę w stanie połączyć te dwie części?
Dzięki
java
inputstream
outputstream
Waypoint
źródło
źródło
new YourOutputStream(thePipedOutputStream)
inew YourInputStream(thePipedInputStream)
który prawdopodobnie nie działa w taki sposób, jak działa Twój strumień. Więc nie sądzę, że to jest rozwiązanie.Odpowiedzi:
Jest
OutputStream
to miejsce, w którym zapisujesz dane. Jeśli jakiś moduł ujawniaOutputStream
, oczekuje się, że na drugim końcu jest coś do odczytania.InputStream
Z drugiej strony coś, co ujawnia , wskazuje, że będziesz musiał wysłuchać tego strumienia i będą dane, które możesz odczytać.Możliwe jest więc podłączenie
InputStream
doOutputStream
InputStream----read---> intermediateBytes[n] ----write----> OutputStream
Jak ktoś wspomniał, na to pozwala
copy()
metoda IOUtils . Nie ma sensu iść w drugą stronę ... mam nadzieję, że ma to jakiś sensAKTUALIZACJA:
Oczywiście im więcej o tym myślę, tym bardziej widzę, jak to właściwie byłoby wymaganiem. Znam niektóre komentarze wspomniane
Piped
strumienie wejścia / wyjścia, ale jest inna możliwość.Jeśli ujawniony strumień wyjściowy to a
ByteArrayOutputStream
, zawsze można uzyskać pełną zawartość, wywołująctoByteArray()
metodę. Następnie możesz utworzyć opakowanie strumienia wejściowego za pomocąByteArrayInputStream
podklasy. Te dwa są pseudo-strumieniami, oba po prostu owijają tablicę bajtów. Dlatego korzystanie ze strumieni w ten sposób jest technicznie możliwe, ale dla mnie nadal jest bardzo dziwne ...źródło
Wydaje się, że istnieje wiele linków i innych podobnych rzeczy, ale nie ma rzeczywistego kodu używającego potoków. Zaletą używania
java.io.PipedInputStream
ijava.io.PipedOutputStream
jest to, że nie ma dodatkowego zużycia pamięci.ByteArrayOutputStream.toByteArray()
zwraca kopię oryginalnego bufora, co oznacza, że cokolwiek masz w pamięci, masz teraz dwie kopie. Pisząc doInputStream
oznacza, że masz teraz trzy kopie danych.Kod:
Ten kod zakłada, że
originalByteArrayOutputStream
jest toByteArrayOutputStream
jako, ponieważ jest to zwykle jedyny możliwy strumień wyjściowy, chyba że piszesz do pliku. Mam nadzieję, że to pomoże! Wspaniałą rzeczą jest to, że ponieważ znajduje się w osobnym wątku, działa również równolegle, więc cokolwiek zużywa strumień wejściowy, będzie również przesyłane strumieniowo ze starego strumienia wyjściowego. Jest to korzystne, ponieważ bufor może pozostać mniejszy, a Ty będziesz mieć mniejsze opóźnienia i mniejsze zużycie pamięci.źródło
out
doin
„s konstruktora, w przeciwnym razie można dostać zamknięty wyjątek na ruryin
z powodu sytuacji wyścigu (co ja doświadczyłem). Korzystanie z Java 8 Lambdas:PipedInputStream in = new PipedInputStream(out); ((Runnable)() -> {originalOutputStream.writeTo(out);}).run(); return in;
originalOutputStream
co powinno być prawdą, ale nie zakłada, jak kontrolujesz swoje strumienie. To zależy od programisty. W tym kodzie nie ma nic, co mogłoby spowodować zamknięty lub zepsuty wyjątek dla potoku.PipedInputStream
Javadocs: Mówi się, że potok jest zepsuty, jeśli wątek dostarczający bajty danych do podłączonego potokowego strumienia wyjściowego już nie żyje. Podejrzewam więc, że jeśli używasz powyższego przykładu, wątek kończy się, zanimJax-RS
zużyje strumień wejściowy. W tym samym czasie spojrzałem na Javadocs MongoDB .GridFSDBFile
ma strumień wejściowy, więc dlaczego nie przekazać go do Jax-RS ?Ponieważ strumienie wejściowe i wyjściowe są tylko punktem początkowym i końcowym, rozwiązaniem jest tymczasowe przechowywanie danych w tablicy bajtów. Musisz więc utworzyć pośredni
ByteArrayOutputStream
, z którego utworzysz,byte[]
który będzie używany jako dane wejściowe dla nowegoByteArrayInputStream
.Mam nadzieję, że to pomoże.
źródło
Będziesz potrzebował klasy pośredniej, która będzie buforować między. Przy każdym
InputStream.read(byte[]...)
wywołaniu klasa buforująca wypełnia przekazaną tablicę bajtów kolejną porcją przekazywaną zOutputStream.write(byte[]...)
. Ponieważ rozmiary porcji mogą nie być takie same, klasa adaptera będzie musiała przechowywać pewną ilość, dopóki nie będzie wystarczająca do zapełnienia bufora odczytu i / lub będzie w stanie zapisać wszelkie przepełnienia bufora.W tym artykule opisano kilka różnych podejść do tego problemu:
http://blog.ostermiller.org/convert-java-outputstream-inputstream
źródło
źródło
toByteArray()
treść metody jest podobna do tej,return Arrays.copyOf(buf, count);
która zwraca nową tablicę.Easystream biblioteka open source ma bezpośredniego wsparcia przekonwertować OutputStream do InputStream: http://io-tools.sourceforge.net/easystream/tutorial/tutorial.html
Wymieniają także inne opcje: http://io-tools.sourceforge.net/easystream/OutputStream_to_InputStream.html
źródło
Napotkałem ten sam problem z konwersją a
ByteArrayOutputStream
na aByteArrayInputStream
i rozwiązałem go za pomocą klasy pochodnej, zByteArrayOutputStream
której jest w stanie zwrócić aByteArrayInputStream
zainicjowany wewnętrznym buforemByteArrayOutputStream
. W ten sposób nie jest wykorzystywana dodatkowa pamięć, a „konwersja” jest bardzo szybka:Kładę rzeczy na github: https://github.com/nickrussler/ByteArrayInOutStream
źródło
Biblioteka io-dodatków może być przydatna. Na przykład, jeśli chcesz gzip
InputStream
użyćGZIPOutputStream
i chcesz, aby stało się to synchronicznie (przy użyciu domyślnego rozmiaru bufora 8192):Zauważ, że biblioteka ma 100% pokrycia testem jednostkowym (oczywiście, co jest tego warte!) I jest dostępna w Maven Central. Zależność Maven to:
Koniecznie sprawdź późniejszą wersję.
źródło
Z mojego punktu widzenia java.io.PipedInputStream / java.io.PipedOutputStream to najlepsza opcja do rozważenia. W niektórych sytuacjach możesz chcieć użyć ByteArrayInputStream / ByteArrayOutputStream. Problem polega na tym, że musisz zduplikować bufor, aby przekonwertować ByteArrayOutputStream na ByteArrayInputStream. Również ByteArrayOutpuStream / ByteArrayInputStream są ograniczone do 2 GB. Oto implementacja OutpuStream / InputStream, którą napisałem, aby ominąć ograniczenia ByteArrayOutputStream / ByteArrayInputStream (kod Scala, ale łatwo zrozumiały dla programistów Java):
Łatwy w użyciu, bez powielania buforów, bez limitu pamięci 2 GB
źródło
Jeśli chcesz utworzyć OutputStream z InputStream, istnieje jeden podstawowy problem. Metoda zapisująca do bloków OutputStream, dopóki nie zostanie wykonana. Tak więc wynik jest dostępny po zakończeniu metody pisania. Ma to 2 konsekwencje:
Wariant 1 może być zaimplementowany przy użyciu tablic bajtowych lub złożony. Wariant 1 można zaimplementować za pomocą pipetów (bezpośrednio lub z dodatkową abstrakcją - np. RingBuffer lub biblioteka Google z innego komentarza).
Rzeczywiście w standardowej Javie nie ma innego sposobu rozwiązania problemu. Każde rozwiązanie jest implementacją jednego z nich.
Istnieje jedna koncepcja zwana „kontynuacją” (szczegóły w Wikipedii ). W tym przypadku w zasadzie oznacza to:
Podczas gdy niektóre języki mają tę wbudowaną koncepcję, java potrzebuje trochę „magii”. Na przykład „commons-javaflow” z apache implementuje takie dla java. Wadą jest to, że wymaga to specjalnych modyfikacji kodu bajtowego podczas kompilacji. Sensowne byłoby więc umieszczenie wszystkich rzeczy w dodatkowej bibliotece z niestandardowymi skryptami kompilacji.
źródło
Stary post, ale może pomóc innym, użyj tego sposobu:
źródło
toString().getBytes()
strumienia * nie zwróci zawartości strumienia.Chociaż nie można przekonwertować OutputStream na InputStream, java zapewnia sposób za pomocą PipedOutputStream i PipedInputStream, że można zapisywać dane w PipedOutputStream, aby stały się dostępne za pośrednictwem powiązanego PipedInputStream.
Kiedyś miałem do czynienia z podobną sytuacją, gdy miałem do czynienia z bibliotekami stron trzecich, które wymagały przekazania do nich instancji InputStream zamiast instancji OutputStream.
Rozwiązałem ten problem, używając PipedInputStream i PipedOutputStream.
Nawiasem mówiąc, są one trudne w użyciu i musisz używać wielowątkowości, aby osiągnąć to, czego chcesz. Niedawno opublikowałem implementację na github, z której możesz korzystać.
Oto link . Możesz przejść przez wiki, aby zrozumieć, jak z niej korzystać.
źródło