입력 스트림을 출력 스트림에 연결
java9 업데이트 : https://docs.oracle.com/javase/9/docs/api/java/io/InputStream.html#transferTo-java.io.OutputStream-
나는 비슷하지만 꼭 필요한 스레드를 보았다.
기본적으로 클라이언트 A 클라이언트로부터 입력을 받아 바이트 단위로 다른 클라이언트 클라이언트 B로 전달하는 서버가 있습니다.
클라이언트 A의 입력 스트림을 클라이언트 B의 출력 스트림과 연결하고 싶습니다. 가능합니까? 그렇게하는 방법은 무엇입니까?
또한 이러한 클라이언트는 시간에 다소 민감한 메시지를 서로 전송하므로 버퍼링이 수행되지 않습니다. 나는 500의 버퍼를 원하지 않고 클라이언트가 499 바이트를 보낸 다음 버퍼를 채우기 위해 마지막 바이트를 수신하지 않았기 때문에 내 서버가 500 바이트 전달을 보류합니다.
지금은 각 메시지를 구문 분석하여 길이를 찾은 다음 길이 바이트를 읽은 다음 전달합니다. 나는 이것이 매우 느리기 때문에 이것이 바이트를 읽고 바이트를 반복해서 전달하는 것보다 낫다고 생각하고 테스트했습니다. 또한 마지막 단락에서 언급 한 이유 때문에 버퍼 나 타이머를 사용하고 싶지 않았습니다. 버퍼가 꽉 찼다는 이유만으로 메시지가 너무 오래 대기하는 것을 원하지 않습니다.
이 작업을 수행하는 좋은 방법은 무엇입니까?
버퍼를 사용한다고해서 스트림이 해당 버퍼 를 채워야 하는 것은 아닙니다 . 즉, 괜찮을 것입니다.
public static void copyStream(InputStream input, OutputStream output)
throws IOException
{
byte[] buffer = new byte[1024]; // Adjust if you want
int bytesRead;
while ((bytesRead = input.read(buffer)) != -1)
{
output.write(buffer, 0, bytesRead);
}
}
그것은 잘 작동합니다-기본적으로 사용 가능한 일부 데이터 read
가있을 때까지 호출이 차단 되지만 버퍼를 채우기 위해 모두 사용할 수 있을 때까지 기다리지 않습니다 . (그럴 수 있다고 생각하고 일반적으로 버퍼 를 채울 것이라고 생각 하지만 소켓에 연결된 스트림이 데이터를 즉시 제공 할 가능성이 더 큽니다.)FileInputStream
이 간단한 솔루션을 먼저 시도해 볼 가치가 있다고 생각합니다.
그냥 사용하는 건 어때
void feedInputToOutput(InputStream in, OutputStream out) {
IOUtils.copy(in, out);
}
그것으로 끝날까요?
이미 엄청난 양의 프로젝트에서 사용되는 jakarta apache commons i / o 라이브러리에서 이미 클래스 경로에 항아리가 이미있을 것입니다.
완전성을 위해 구아바 는이를위한 편리한 유틸리티도 제공합니다.
ByteStreams.copy(input, output);
InputStream#transferTo(OutputStream out)
이 기능을 위해 JDK 9 가 추가되었습니다 .
순환 버퍼를 사용할 수 있습니다.
암호
// buffer all data in a circular buffer of infinite size
CircularByteBuffer cbb = new CircularByteBuffer(CircularByteBuffer.INFINITE_SIZE);
class1.putDataOnOutputStream(cbb.getOutputStream());
class2.processDataFromInputStream(cbb.getInputStream());
Maven 종속성
<dependency>
<groupId>org.ostermiller</groupId>
<artifactId>utils</artifactId>
<version>1.07.00</version>
</dependency>
모드 세부 정보
http://ostermiller.org/utils/CircularBuffer.html
그것을 달성하는 비동기 방식.
void inputStreamToOutputStream(final InputStream inputStream, final OutputStream out) {
Thread t = new Thread(new Runnable() {
public void run() {
try {
int d;
while ((d = inputStream.read()) != -1) {
out.write(d);
}
} catch (IOException ex) {
//TODO make a callback on exception.
}
}
});
t.setDaemon(true);
t.start();
}
BUFFER_SIZE는 읽을 척의 크기입니다.> 1kb 및 <10MB 여야합니다.
private static final int BUFFER_SIZE = 2 * 1024 * 1024;
private void copy(InputStream input, OutputStream output) throws IOException {
try {
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead = input.read(buffer);
while (bytesRead != -1) {
output.write(buffer, 0, bytesRead);
bytesRead = input.read(buffer);
}
//If needed, close streams.
} finally {
input.close();
output.close();
}
}
org.apache.commons.io.IOUtils 사용
InputStream inStream = new ...
OutputStream outStream = new ...
IOUtils.copy(inStream, outStream);
또는 2GB를 초과 하는 크기의 경우 copyLarge
이것은 깨끗하고 빠른 Scala 버전입니다 (스택 오버플로 없음).
import scala.annotation.tailrec
import java.io._
implicit class InputStreamOps(in: InputStream) {
def >(out: OutputStream): Unit = pipeTo(out)
def pipeTo(out: OutputStream, bufferSize: Int = 1<<10): Unit = pipeTo(out, Array.ofDim[Byte](bufferSize))
@tailrec final def pipeTo(out: OutputStream, buffer: Array[Byte]): Unit = in.read(buffer) match {
case n if n > 0 =>
out.write(buffer, 0, n)
pipeTo(out, buffer)
case _ =>
in.close()
out.close()
}
}
이를 통해 >
예를 들어 기호 를 사용할 수 inputstream > outputstream
있으며 사용자 정의 버퍼 / 크기도 전달할 수 있습니다.
만약 당신이 기능적으로 작동한다면 이것은 (vars가 아닌) vals만을 사용하여 출력 스트림에 입력 스트림을 복사하는 방법을 보여주는 Scala로 작성된 함수입니다.
def copyInputToOutputFunctional(inputStream: InputStream, outputStream: OutputStream,bufferSize: Int) {
val buffer = new Array[Byte](bufferSize);
def recurse() {
val len = inputStream.read(buffer);
if (len > 0) {
outputStream.write(buffer.take(len));
recurse();
}
}
recurse();
}
재귀 함수를 사용하면 스택 오버플로 예외 오류가 쉽게 발생할 수 있으므로 사용 가능한 메모리가 거의없는 Java 응용 프로그램에서는 사용하지 않는 것이 좋습니다.
참고URL : https://stackoverflow.com/questions/1574837/connecting-an-input-stream-to-an-outputstream
'Nice programing' 카테고리의 다른 글
styles.xml에서 프로그래밍 방식으로 스타일 속성을 검색하는 방법 (0) | 2020.10.25 |
---|---|
현재 위치를 시작 주소로 사용하여 길 찾기에 대한 iPhone지도를 호출하는 방법 (0) | 2020.10.25 |
Eclipse의 초보자, "동적 웹 프로젝트"가 없습니다. Linux Ubuntu에 있습니다. (0) | 2020.10.25 |
Html.EditorFor 기본값 설정 (0) | 2020.10.25 |
Golang : 인쇄 할 때 숫자를 0으로 채우는 방법은 무엇입니까? (0) | 2020.10.25 |