이 페이지 : http://blog.ostermiller.org/convert-java-outputstream-inputstream
은 OutputStream에서 InputStream을 만드는 방법을 설명합니다.
new ByteArrayInputStream(out.toByteArray())
다른 대안은 PipedStreams와 번거로운 새 스레드를 사용하는 것입니다.
나는 많은 메가 바이트를 메모리 바이트 배열에서 새로운 것으로 복사하는 아이디어를 좋아하지 않습니다. 이 작업을보다 효율적으로 수행하는 라이브러리가 있습니까?
편집하다:
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))
답변
모든 데이터를 한꺼번에 메모리 내 버퍼에 복사하지 않으려면 OutputStream (생산자)을 사용하는 코드와 InputStream (소비자)을 사용하는 코드가 있어야합니다. ) 동일한 스레드에서 번갈아 가거나 두 개의 개별 스레드에서 동시에 작동합니다. 동일한 스레드에서 작동하도록하는 것은 두 개의 개별 스레드를 사용하는 것보다 훨씬 더 복잡하고 오류가 발생하기 쉽습니다 (소비자 가 입력 대기를 차단 하지 않도록해야합니다. 그렇지 않으면 효과적으로 교착 상태가 될 것입니다). 생산자와 소비자가 너무 밀접하게 결합 된 것처럼 보이는 동일한 루프에서 실행되는 것.
따라서 두 번째 스레드를 사용하십시오. 정말 그렇게 복잡하지 않습니다. 링크 한 페이지에는 완벽한 예가 있습니다.
PipedInputStream in = new PipedInputStream();
PipedOutputStream out = new PipedOutputStream(in);
new Thread(
new Runnable(){
public void run(){
class1.putDataOnOutputStream(out);
}
}
).start();
class2.processDataFromInputStream(in);
답변
파이프와 스레드를 투명한 방식으로 처리하는 EasyStream 이라는 또 다른 오픈 소스 라이브러리 가 있습니다. 모든 것이 잘되면 그렇게 복잡하지 않습니다. (로렌스 곤살 베스 예를 보면) 문제가 발생합니다.
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)
}
};
OutputStream을 InputStream으로 변환하는 다른 모든 방법을 설명 하는 멋진 소개 도 있습니다 . 볼 가치가 있습니다.
답변
버퍼 복사를 피하는 간단한 해결책은 특수 목적을 만드는 것입니다 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
하여 기본 버퍼를 통해 입력 스트림을 가져옵니다. 해당 시점 이후에 출력 스트림이 닫힌 것으로 간주하십시오.
답변
InputStream을 OutputStream에 연결하는 가장 좋은 방법 은 다음과 같이 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-데이터 대기열을 수동으로 처리 할 필요가 없습니다.
답변
나는 일반적으로 교착 상태의 증가, 코드 이해의 어려움 증가 및 예외 처리 문제로 인해 별도의 스레드 생성을 피하려고합니다.
내 제안 된 솔루션은 다음과 같습니다. ProducerInputStream은 반복적으로 ProduceChunk () 호출을 통해 콘텐츠를 생성합니다.
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);
}