문제

이 페이지: http://blog.ostermiller.org/convert-java outputstream-inputstreamOutputStream에서 입력 스트림을 만드는 방법을 설명합니다.

new ByteArrayInputStream(out.toByteArray())

다른 대안은 파이프 스트림과 새로운 스레드를 사용하는 것입니다.

나는 많은 메가 바이트를 메모리 바이트 배열에 새로운 메가 바이트를 복사한다는 아이디어를 좋아하지 않습니다. 이것을 더 효율적으로 수행하는 라이브러리가 있습니까?

편집하다:

Laurence Gonsalves의 조언으로, 나는 Pipedstreams를 시도했고 그들이 다루기가 어렵지 않다는 것이 밝혀졌습니다. Clojure의 샘플 코드는 다음과 같습니다.

(defn #^PipedInputStream create-pdf-stream [pdf-info]
  (let [in-stream (new PipedInputStream)
        out-stream (PipedOutputStream. in-stream)]
    (.start (Thread. #(;Here you write into out-stream)))
    in-stream))
도움이 되었습니까?

해결책

모든 데이터를 메모리 인 메모리 버퍼에 한 번에 복사하지 않으려면 출력 스트림 (생산자)과 입력 스트림 (소비자를 사용하는 코드를 사용하는 코드가 있어야합니다. ) 동일한 스레드에서 번갈아 가거나 두 개의 별도 스레드에서 동시에 작동합니다. 동일한 스레드에서 작동하게하는 것은 아마도 두 개의 별도 스레드를 사용하는 것이 훨씬 더 복잡 할 것입니다. 절대 입력을 기다리는 블록이 있거나 효과적으로 교착 상태) 생산자와 소비자가 너무 단단히 결합 된 것처럼 보이는 동일한 루프에서 실행해야합니다.

따라서 두 번째 스레드를 사용하십시오. 정말 복잡하지 않습니다. 당신이 링크 한 페이지에는 완벽한 예가 있습니다.

  PipedInputStream in = new PipedInputStream();
  PipedOutputStream out = new PipedOutputStream(in);
  new Thread(
    new Runnable(){
      public void run(){
        class1.putDataOnOutputStream(out);
      }
    }
  ).start();
  class2.processDataFromInputStream(in);

다른 팁

다른 오픈 소스 라이브러리가 있습니다 EasyStream 이는 파이프와 스레드를 투명한 방식으로 다룹니다. 모든 것이 잘되면 그것은 실제로 복잡하지 않습니다. 문제가 발생할 때 발생합니다 (Laurence Gonsalves 예를 보면)

class1.putDataOnoutputStream (out);

예외를 던집니다. 이 예에서는 스레드가 단순히 완료되고 예외가 손실되고 외부는 InputStream 잘릴 수 있습니다.

EasyStream은 예외 전파 및 약 1 년 동안 디버깅을 한 기타 불쾌한 문제를 처리합니다. (저는 도서관의 맨테이너입니다. 분명히 내 솔루션은 가장 좋은 것입니다.)) 여기에 사용 방법에 대한 예입니다.

final InputStreamFromOutputStream<String> isos = new InputStreamFromOutputStream<String>(){
 @Override
 public String produce(final OutputStream dataSink) throws Exception {
   /*
    * call your application function who produces the data here
    * WARNING: we're in another thread here, so this method shouldn't 
    * write any class field or make assumptions on the state of the outer class. 
    */
   return produceMydata(dataSink)
 }
};

좋은 것도 있습니다 소개 출력 스트림을 입력 스트림으로 변환하는 다른 모든 방법이 설명됩니다. 살펴볼 가치가 있습니다.

버퍼 복사를 피하는 간단한 솔루션은 특수 목적을 만드는 것입니다. ByteArrayOutputStream:

public class CopyStream extends ByteArrayOutputStream {
    public CopyStream(int size) { super(size); }

    /**
     * Get an input stream based on the contents of this output stream.
     * Do not use the output stream after calling this method.
     * @return an {@link InputStream}
     */
    public InputStream toInputStream() {
        return new ByteArrayInputStream(this.buf, 0, this.count);
    }
}

필요에 따라 위의 출력 스트림에 쓰고 toInputStream 기본 버퍼에 대한 입력 스트림을 얻습니다. 그 시점 이후에 출력 스트림을 닫은 것으로 간주하십시오.

입력 스트림을 출력 스트림에 연결하는 가장 좋은 방법은 파이프 스트림 - java.io 패키지로 제공됩니다.

// 1- Define stream buffer
private static final int PIPE_BUFFER = 2048;

// 2 -Create PipedInputStream with the buffer
public PipedInputStream inPipe = new PipedInputStream(PIPE_BUFFER);

// 3 -Create PipedOutputStream and bound it to the PipedInputStream object
public PipedOutputStream outPipe = new PipedOutputStream(inPipe);

// 4- PipedOutputStream is an OutputStream, So you can write data to it
// in any way suitable to your data. for example:
while (Condition) {
     outPipe.write(mByte);
}

/*Congratulations:D. Step 4 will write data to the PipedOutputStream
which is bound to the PipedInputStream so after filling the buffer
this data is available in the inPipe Object. Start reading it to
clear the buffer to be filled again by the PipedInputStream object.*/

제 생각에는이 코드의 두 가지 주요 장점이 있습니다.

1- 버퍼를 제외하고는 메모리 소비가 없습니다.

2- 수동으로 데이터 대기열을 처리 할 필요가 없습니다.

나는 일반적으로 교착 상태의 확률 증가, 코드 이해가 어려워지고 예외를 다루는 문제로 인해 별도의 스레드를 생성하지 않으려 고 노력합니다.

제안 된 솔루션은 다음과 같습니다. ProduceChunk ()에 대한 반복적 인 호출로 청크에서 컨텐츠를 생성하는 ProducerInputStream : :

public abstract class ProducerInputStream extends InputStream {

    private ByteArrayInputStream bin = new ByteArrayInputStream(new byte[0]);
    private ByteArrayOutputStream bout = new ByteArrayOutputStream();

    @Override
    public int read() throws IOException {
        int result = bin.read();
        while ((result == -1) && newChunk()) {
            result = bin.read();
        }
        return result;
    }

    @Override
    public int read(byte[] b, int off, int len) throws IOException {
        int result = bin.read(b, off, len);
        while ((result == -1) && newChunk()) {
            result = bin.read(b, off, len);
        }
        return result;
    }

    private boolean newChunk() {
        bout.reset();
        produceChunk(bout);
        bin = new ByteArrayInputStream(bout.toByteArray());
        return (bout.size() > 0);
    }

    public abstract void produceChunk(OutputStream out);

}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top