Domanda

Avendo due InputStreams in Java, c'è un modo per unirle così si finisce con un InputStream che ti dà l'uscita di entrambi i flussi? Come?

È stato utile?

Soluzione

Come commentato, non è chiaro cosa si intende per unione.

Prendendo a disposizione di ingresso "a caso" da entrambi è complicata dal InputStream.available non necessariamente ti dà una risposta utile e bloccando il comportamento dei flussi. Si avrebbe bisogno di due fili di leggere dai ruscelli e poi passando di nuovo i dati attraverso, per esempio, java.io.Piped(In|Out)putStream (anche se quelle classi hanno problemi). In alternativa, per alcuni tipi di flusso può essere possibile utilizzare una diversa interfaccia, ad esempio java.nio canali non bloccanti.

Se si desidera che l'intero contenuto del primo flusso di input seguito dal secondo:. new java.io.SequenceInputStream(s1, s2)

Altri suggerimenti

java.io.SequenceInputStream potrebbe essere quello che ti serve. Esso accetta un'enumerazione di flussi, e stamperà il contenuto del primo flusso, poi la seconda, e così via fino a che tutti i flussi sono vuoti.

È possibile scrivere un'implementazione InputStream personalizzato che fa questo. Esempio:

import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.Deque;
import java.util.LinkedList;

public class CatInputStream extends InputStream {
    private final Deque<InputStream> streams;

    public CatInputStream(InputStream... streams) {
        this.streams = new LinkedList<InputStream>();
        Collections.addAll(this.streams, streams);
    }

    private void nextStream() throws IOException {
        streams.removeFirst().close();
    }

    @Override
    public int read() throws IOException {
        int result = -1;
        while (!streams.isEmpty()
                && (result = streams.getFirst().read()) == -1) {
            nextStream();
        }
        return result;
    }

    @Override
    public int read(byte b[], int off, int len) throws IOException {
        int result = -1;
        while (!streams.isEmpty()
                && (result = streams.getFirst().read(b, off, len)) == -1) {
            nextStream();
        }
        return result;
    }

    @Override
    public long skip(long n) throws IOException {
        long skipped = 0L;
        while (skipped < n && !streams.isEmpty()) {
            int thisSkip = streams.getFirst().skip(n - skipped);
            if (thisSkip > 0)
                skipped += thisSkip;
            else
                nextStream();
        }
        return skipped;
    }

    @Override
    public int available() throws IOException {
        return streams.isEmpty() ? 0 : streams.getFirst().available();
    }

    @Override
    public void close() throws IOException {
        while (!streams.isEmpty())
            nextStream();
    }
}

Questo codice non è testato, così il vostro chilometraggio può variare.

Non è che mi viene in mente. Probabilmente si dovrà leggere il contenuto dei due flusso in un byte [] e quindi creare un ByteArrayInputStream da questo.

Ecco un'implementazione MVAR specifico array di byte (assicuratevi di aggiungere la tua definizione del pacchetto). Da qui, è banale scrivere un flusso di input sui flussi unite. Posso inviare anche questo, se richiesto.

import java.nio.ByteBuffer;

public final class MVar {

  private static enum State {
    EMPTY, ONE, MANY
  }

  private final Object lock;

  private State state;

  private byte b;

  private ByteBuffer bytes;
  private int length;

  public MVar() {
    lock = new Object();
    state = State.EMPTY;
  }

  public final void put(byte b) {
    synchronized (lock) {
      while (state != State.EMPTY) {
        try {
          lock.wait();
        } catch (InterruptedException e) {}
      }
      this.b = b;
      state = State.ONE;
      lock.notifyAll();
    }
  }

  public final void put(byte[] bytes, int offset, int length) {
    if (length == 0) {
      return;
    }
    synchronized (lock) {
      while (state != State.EMPTY) {
        try {
          lock.wait();
        } catch (InterruptedException e) {}
      }
      this.bytes = ByteBuffer.allocateDirect(length);
      this.bytes.put(bytes, offset, length);
      this.bytes.position(0);
      this.length = length;
      state = State.MANY;
      lock.notifyAll();
    }
  }

  public final byte take() {
    synchronized (lock) {
      while (state == State.EMPTY) {
        try {
          lock.wait();
        } catch (InterruptedException e) {}
      }
      switch (state) {
      case ONE: {
        state = State.EMPTY;
        byte b = this.b;
        lock.notifyAll();
        return b;
      }
      case MANY: {
        byte b = bytes.get();
        state = --length <= 0 ? State.EMPTY : State.MANY;
        lock.notifyAll();
        return b;
      }
      default:
        throw new AssertionError();
      }
    }
  }

  public final int take(byte[] bytes, int offset, int length) {
    if (length == 0) {
      return 0;
    }
    synchronized (lock) {
      while (state == State.EMPTY) {
        try {
          lock.wait();
        } catch (InterruptedException e) {}
      }
      switch (state) {
      case ONE:
        bytes[offset] = b;
        state = State.EMPTY;
        lock.notifyAll();
        return 1;
      case MANY:
        if (this.length > length) {
          this.bytes.get(bytes, offset, length);
          this.length = this.length - length;
          synchronized (lock) {
            lock.notifyAll();
          }
          return length;
        }
        this.bytes.get(bytes, offset, this.length);
        this.bytes = null;
        state = State.EMPTY;
        length = this.length;
        lock.notifyAll();
        return length;
      default:
        throw new AssertionError();
      }
    }
  }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top