164 Stimmen

Eingabestrom zweimal lesen

Wie kann man denselben Inputstream zweimal lesen? Ist es möglich, ihn irgendwie zu kopieren?

Ich muss ein Bild aus dem Internet abrufen, es lokal speichern und dann das gespeicherte Bild zurückgeben. Ich dachte nur, es wäre schneller, den gleichen Stream zu verwenden, anstatt einen neuen Stream zum heruntergeladenen Inhalt zu starten und ihn dann erneut zu lesen.

7voto

alain.janinm Punkte 19495

Wenn Sie eine Implementierung von InputStream können Sie das Ergebnis von InputStream#markSupported() die Ihnen sagen, ob Sie die Methode verwenden können oder nicht mark() / reset() .

Wenn Sie den Stream beim Lesen markieren können, dann rufen Sie reset() zurückgehen, um zu beginnen.

Wenn Sie das nicht können, müssen Sie erneut einen Stream öffnen.

Eine andere Lösung wäre, InputStream in ein Byte-Array zu konvertieren und dann über das Array so oft zu iterieren, wie Sie benötigen. Sie können mehrere Lösungen in diesem Beitrag finden Umwandlung von InputStream in Byte-Array in Java Verwendung von Drittanbieter-Libs oder nicht. Vorsicht, wenn der gelesene Inhalt zu groß ist, kann es zu Speicherproblemen kommen.

Wenn Sie schließlich ein Bild lesen möchten, verwenden Sie :

BufferedImage image = ImageIO.read(new URL("http://www.example.com/images/toto.jpg"));

使用する ImageIO#read(java.net.URL) können Sie auch den Cache verwenden.

4voto

milosmns Punkte 3168

Für den Fall, dass jemand in einer Spring Boot-Anwendung läuft und Sie den Antwortkörper einer RestTemplate (weshalb ich einen Stream zweimal lesen möchte), gibt es einen sauberen Weg, dies zu tun.

Zuallererst müssen Sie die Spring-Funktion StreamUtils um den Stream in einen String zu kopieren:

String text = StreamUtils.copyToString(response.getBody(), Charset.defaultCharset()))

Aber das ist noch nicht alles. Sie müssen auch eine Anforderungsfabrik verwenden, die den Stream für Sie puffern kann, etwa so:

ClientHttpRequestFactory factory = new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory());
RestTemplate restTemplate = new RestTemplate(factory);

Oder, wenn Sie die Fabrik Bohne verwenden, dann (dies ist Kotlin aber trotzdem):

@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
fun createRestTemplate(): RestTemplate = RestTemplateBuilder()
  .requestFactory { BufferingClientHttpRequestFactory(SimpleClientHttpRequestFactory()) }
  .additionalInterceptors(loggingInterceptor)
  .build()

Quelle: https://objectpartners.com/2018/03/01/log-your-resttemplate-request-and-response-without-destroying-the-body/

3voto

Wie wäre es damit:

if (stream.markSupported() == false) {

        // lets replace the stream object
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        IOUtils.copy(stream, baos);
        stream.close();
        stream = new ByteArrayInputStream(baos.toByteArray());
        // now the stream should support 'mark' and 'reset'

    }

2voto

Maneesh Punkte 6028

Konvertieren Sie den Eingabestrom in Bytes und übergeben Sie ihn dann an die Funktion savefile, wo Sie ihn in den Eingabestrom zusammensetzen. Auch in der ursprünglichen Funktion werden Bytes für andere Aufgaben verwendet

0voto

Noman Khan Punkte 880

Wenn Sie RestTemplate für http-Aufrufe verwenden, fügen Sie einfach einen Interceptor hinzu. Der Antwortkörper wird von der Implementierung von ClientHttpResponse zwischengespeichert. Jetzt kann der Inputstream so oft wie nötig aus der Antwort abgerufen werden

ClientHttpRequestInterceptor interceptor =  new ClientHttpRequestInterceptor() {

            @Override
            public ClientHttpResponse intercept(HttpRequest request, byte[] body,
                    ClientHttpRequestExecution execution) throws IOException {
                ClientHttpResponse  response = execution.execute(request, body);

                  // additional work before returning response
                  return response 
            }
        };

    // Add the interceptor to RestTemplate Instance 

         restTemplate.getInterceptors().add(interceptor);

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X