programing

Java InputStream의 콘텐츠를 OutputStream에 쉽게 쓰는 방법

prostudy 2022. 7. 21. 23:59
반응형

Java InputStream의 콘텐츠를 OutputStream에 쉽게 쓰는 방법

오늘 깜짝 놀랐어요.그동안의 내용을 간단하게 쓸 수 있는 방법을 찾을 수 없었습니다.InputStream에 대해서OutputStream자바어.물론 바이트 버퍼 코드는 쓰기 어렵지 않지만, 내 삶을 더 쉽게 만들 수 있는 무언가를 놓치고 있는 것 같습니다(그리고 코드도 더 선명합니다).

그러니까,InputStream in그리고OutputStream out, 다음과 같이 간단하게 쓸 수 있는 방법이 있습니까?

byte[] buffer = new byte[1024];
int len = in.read(buffer);
while (len != -1) {
    out.write(buffer, 0, len);
    len = in.read(buffer);
}

WMR이 말했듯이org.apache.commons.io.IOUtilsApache의 수법이 있습니다.그것은 당신이 찾고 있는 것과 정확히 일치합니다.

다음과 같은 것이 있습니다.

InputStream in;
OutputStream out;
IOUtils.copy(in,out);
in.close();
out.close();

당신의 암호로.

당신이 피해가는 이유가 있나요?IOUtils?

Java 7을 사용하는 경우 표준 라이브러리의 파일(Files)이 최선의 방법입니다.

/* You can get Path from file also: file.toPath() */
Files.copy(InputStream in, Path target)
Files.copy(Path source, OutputStream out)

편집: 물론 파일에서 InputStream 또는 OutputStream 중 하나를 작성할 때 유용합니다.사용하다file.toPath()파일에서 경로를 가져옵니다.

기존 파일(예: 로 작성된 파일)에 쓰려면File.createTempFile()) 。를 통과해야 합니다.REPLACE_EXISTING복사 옵션(복사)FileAlreadyExistsException투척됩니다).

Files.copy(in, target, StandardCopyOption.REPLACE_EXISTING)

자바 9

Java 9 이후InputStream라고 하는 메서드를 제공합니다.transferTo다음 시그니처를 사용합니다.

public long transferTo(OutputStream out) throws IOException

서류에 나와 있듯이transferTo의 내용:

이 입력 스트림에서 모든 바이트를 읽고 읽기 순서대로 지정된 출력 스트림에 바이트를 씁니다.반환되는 경우 이 입력 스트림은 스트림의 끝에 있습니다.이 메서드는 어느 스트림도 닫히지 않습니다.

이 메서드는 입력 스트림에서 읽거나 출력 스트림에 쓰는 것을 무기한 차단할 수 있습니다.입력 및/또는 출력 스트림이 비동기적으로 닫히거나 전송 중에 스레드가 중단된 경우 동작은 입력 및 출력 스트림에 따라 매우 다르므로 지정되지 않습니다.

그래서 자바 콘텐츠를 작성하기 위해서InputStream에 대해서OutputStream, 다음과 같이 쓸 수 있습니다.

input.transferTo(output);

이거면 될 것 같은데 꼭 테스트...사소한 '개선'도 있지만 읽기 쉽기 때문에 비용이 많이 들 수 있습니다.

byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer)) != -1) {
    out.write(buffer, 0, len);
}

Guava 사용:

ByteStreams.copy(inputStream, outputStream);

심플한 기능

이 명령어가 필요한 경우에만InputStream에 대해서File다음 간단한 기능을 사용할 수 있습니다.

private void copyInputStreamToFile( InputStream in, File file ) {
    try {
        OutputStream out = new FileOutputStream(file);
        byte[] buf = new byte[1024];
        int len;
        while((len=in.read(buf))>0){
            out.write(buf,0,len);
        }
        out.close();
        in.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

JDK는 같은 코드를 사용하기 때문에, 투박한 서드파티 라이브러리가 없으면 「불필요한」방법은 없는 것 같습니다(어차피 다른 것은 아무것도 하지 않습니다).다음은 에서 직접 복사한 것입니다.java.nio.file.Files.java:

// buffer size used for reading and writing
private static final int BUFFER_SIZE = 8192;

/**
  * Reads all bytes from an input stream and writes them to an output stream.
  */
private static long copy(InputStream source, OutputStream sink) throws IOException {
    long nread = 0L;
    byte[] buf = new byte[BUFFER_SIZE];
    int n;
    while ((n = source.read(buf)) > 0) {
        sink.write(buf, 0, n);
        nread += n;
    }
    return nread;
}

Spring 프레임워크를 사용하는 사용자에게 유용한 Stream Utils 클래스가 있습니다.

StreamUtils.copy(in, out);

위의 경우 스트림이 닫히지 않습니다.복사 후 스트림을 닫으려면 FileCopyUtils 클래스를 대신 사용합니다.

FileCopyUtils.copy(in, out);

PipedInputStream ★★★★★★★★★★★★★★★★★」PipedOutputStreamJavadoc에서 설명한 바와 같이 여러 스레드가 있는 경우에만 사용해야 합니다.

입력 은 스레드 을 ""로.IOException 코드에 을 도입하는 것을 . 따라서 코드에 인터럽트 정책을 도입하는 것을 검토해야 합니다.

byte[] buffer = new byte[1024];
int len = in.read(buffer);
while (len != -1) {
    out.write(buffer, 0, len);
    len = in.read(buffer);
    if (Thread.interrupted()) {
        throw new InterruptedException();
    }
}

이 API를 사용하여 대량의 데이터를 복사하거나 스트림에서 장시간 정지된 데이터를 복사할 경우 유용합니다.

JDK 방식으로는 이 작업을 쉽게 수행할 수 없지만 Apocalisp가 이미 언급했듯이 이 아이디어를 가진 사람은 당신뿐만이 아닙니다.자카르타 Commons IO에서 IOUtils를 사용할 수 있습니다.IMO가 JDK의 일부여야 하는 기타 유용한 기능도 많이 있습니다.

Java7 및 리소스 사용 시 간결하고 읽기 쉬운 버전이 제공됩니다.

try(InputStream inputStream = new FileInputStream("C:\\mov.mp4");
    OutputStream outputStream = new FileOutputStream("D:\\mov.mp4")) {

    byte[] buffer = new byte[10*1024];

    for (int length; (length = inputStream.read(buffer)) != -1; ) {
        outputStream.write(buffer, 0, length);
    }
} catch (FileNotFoundException exception) {
    exception.printStackTrace();
} catch (IOException ioException) {
    ioException.printStackTrace();
}

가장 간단한 for loop을 사용하는 방법을 소개합니다.

private void copy(final InputStream in, final OutputStream out)
    throws IOException {
    final byte[] b = new byte[8192];
    for (int r; (r = in.read(b)) != -1;) {
        out.write(b, 0, r);
    }
}

Commons Net의 Util 클래스 사용:

import org.apache.commons.net.io.Util;
...
Util.copyStream(in, out);

용 i i i i를 쓴다.BufferedInputStream ★★★★★★★★★★★★★★★★★」BufferedOutputStream에서

try (OutputStream out = new BufferedOutputStream(...);
     InputStream in   = new BufferedInputStream(...))) {
  int ch;
  while ((ch = in.read()) != -1) {
    out.write(ch);
  }
}

IMHO 보다 최소화된 스니펫(길이 변수 범위도 좁음):

byte[] buffer = new byte[2048];
for (int n = in.read(buffer); n >= 0; n = in.read(buffer))
    out.write(buffer, 0, n);

왜 더 많은 더 많이 수 .for루 loop loop loop loop loop loop loop loop 。while"불량한" 스타일로 간주되는 할당 및 테스트 표현과 함께.

대부분의 파일이 1024바이트보다 크기 때문에 큰 버퍼를 사용하는 것이 좋다고 생각합니다.또한 읽기 바이트 수가 양수인지 확인하는 것이 좋습니다.

byte[] buffer = new byte[4096];
int n;
while ((n = in.read(buffer)) > 0) {
    out.write(buffer, 0, n);
}
out.close();

이게 내 최선이야!!

그리고 너무 일반적이기 때문에 사용하지 마세요.버퍼 메모리를 제어하면 코드 성능이 향상됩니다.

public static void transfer(InputStream in, OutputStream out, int buffer) throws IOException {
    byte[] read = new byte[buffer]; // Your buffer size.
    while (0 < (buffer = in.read(read)))
        out.write(read, 0, buffer);
}

스트림의 크기를 미리 알고 있을 때 이 (개선 가능한) 방법으로 사용하고 있습니다.

public static void transfer(int size, InputStream in, OutputStream out) throws IOException {
    transfer(in, out,
            size > 0xFFFF ? 0xFFFF // 16bits 65,536
                    : size > 0xFFF ? 0xFFF// 12bits 4096
                            : size < 0xFF ? 0xFF // 8bits 256
                                    : size
    );
}

읽기 쉽지는 않지만 효과적이며 의존성이 없으며 Java 버전에서도 실행 가능

byte[] buffer=new byte[1024];
for(int n; (n=inputStream.read(buffer))!=-1; outputStream.write(buffer,0,n));

PipedInputStream과 PipedOutputStream은 서로 연결할 수 있으므로 도움이 될 수 있습니다.

다른 후보로는 Guava I/O 유틸리티가 있습니다.

http://code.google.com/p/guava-libraries/wiki/IOExplained

Guava는 이미 내 프로젝트에서 매우 유용하기 때문에 한 가지 기능을 위해 다른 라이브러리를 추가하는 것보다 이것들을 사용해야겠다고 생각했습니다.

하였습니다.ByteStreamKt.copyTo(src, dst, buffer.length)

여기 제 코드가 있습니다.

public static void replaceCurrentDb(Context context, Uri newDbUri) {
    try {
        File currentDb = context.getDatabasePath(DATABASE_NAME);
        if (currentDb.exists()) {
            InputStream src = context.getContentResolver().openInputStream(newDbUri);
            FileOutputStream dst = new FileOutputStream(currentDb);
            final byte[] buffer = new byte[8 * 1024];
            ByteStreamsKt.copyTo(src, dst, buffer.length);
            src.close();
            dst.close();
            Toast.makeText(context, "SUCCESS! Your selected file is set as current menu.", Toast.LENGTH_LONG).show();
        }
        else
            Log.e("DOWNLOAD:::: Database", " fail, database not found");
    }
    catch (IOException e) {
        Toast.makeText(context, "Data Download FAIL.", Toast.LENGTH_LONG).show();
        Log.e("DOWNLOAD FAIL!!!", "fail, reason:", e);
    }
}
public static boolean copyFile(InputStream inputStream, OutputStream out) {
    byte buf[] = new byte[1024];
    int len;
    long startTime=System.currentTimeMillis();

    try {
        while ((len = inputStream.read(buf)) != -1) {
            out.write(buf, 0, len);
        }

        long endTime=System.currentTimeMillis()-startTime;
        Log.v("","Time taken to transfer all bytes is : "+endTime);
        out.close();
        inputStream.close();

    } catch (IOException e) {

        return false;
    }
    return true;
}

선인장 체험:

new LengthOf(new TeeInput(input, output)).value();

상세한 것에 대하여는, http://www.yegor256.com/2017/06/22/object-oriented-input-output-in-cactoos.html 를 참조해 주세요.

이 방법을 사용할 수 있습니다.

public static void copyStream(InputStream is, OutputStream os)
 {
     final int buffer_size=1024;
     try
     {
         byte[] bytes=new byte[buffer_size];
         for(;;)
         {
           int count=is.read(bytes, 0, buffer_size);
           if(count==-1)
               break;
           os.write(bytes, 0, count);
         }
     }
     catch(Exception ex){}
 }

언급URL : https://stackoverflow.com/questions/43157/easy-way-to-write-contents-of-a-java-inputstream-to-an-outputstream

반응형