문제

나는 오늘 내용을 작성하는 간단한 방법을 찾을 수 없다는 사실에 놀랐습니다. InputStreamOutputStream 자바에서.분명히 바이트 버퍼 코드는 작성하기 어렵지 않지만 내 삶을 더 쉽게(그리고 코드를 더 명확하게) 만들어 줄 뭔가가 빠진 것 같습니다.

그래서 주어진 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);
}
도움이 되었습니까?

해결책

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

/* 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)

다른 팁

WMR이 언급했듯이, org.apache.commons.io.IOUtils Apache에는 다음과 같은 메소드가 있습니다. copy(InputStream,OutputStream) 정확히 당신이 찾고 있는 것을 수행합니다.

따라서 다음과 같은 이점이 있습니다.

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

...귀하의 코드에서.

피하는 이유가 있나요 IOUtils?

자바 9

자바 9부터 InputStream 라는 메소드를 제공합니다. transferTo 다음 서명을 사용합니다.

public long transferTo(OutputStream out) throws IOException

다음과 같이 선적 서류 비치 상태, transferTo 할 것이다:

이 입력 스트림의 모든 바이트를 읽고 읽기 순서대로 주어진 출력 스트림에 바이트를 씁니다.반환하면이 입력 스트림이 스트림 끝에 있습니다.이 메소드는 스트림을 모두 닫지 않습니다.

이 방법은 입력 스트림에서 무기한 읽기 또는 출력 스트림에 쓰기를 차단할 수 있습니다.입력 및/또는 출력 스트림이 비동기식으로 닫히거나 전송 중에 스레드가 중단 된 경우에 대한 동작은 입력 및 출력 스트림에 따라 구체적이지 않아 지정되지 않습니다.

따라서 Java의 내용을 작성하려면 InputStreamOutputStream, 당신은 쓸 수 있습니다:

input.transferTo(output);

이것이 효과가 있을 것 같지만 꼭 테스트해 보세요...사소한 "개선"이지만 가독성 측면에서는 약간의 비용이 들 수 있습니다.

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

구아바를 사용하여 ByteStreams.copy():

ByteStreams.copy(inputStream, outputStream);

간단한 기능

글쓰기에만 이것이 필요한 경우 InputStreamFile 그러면 다음과 같은 간단한 기능을 사용할 수 있습니다.

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();
    }
}

PipedInputStream 그리고 PipedOutputStream 여러 스레드가 있는 경우에만 사용해야 합니다. Javadoc에서 언급한.

또한 입력 스트림과 출력 스트림은 스레드 중단을 다음과 같이 래핑하지 않습니다. 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 동일한 코드를 사용하므로 투박한 타사 라이브러리 없이는 "더 쉬운" 방법은 없는 것처럼 보입니다(아마도 다른 작업은 수행하지 않을 것입니다).다음은 다음에서 직접 복사됩니다. 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;
    }

이용하시는 분들을 위해 스프링 프레임워크 유용한 것이있다 StreamUtils 수업:

StreamUtils.copy(in, out);

위의 내용은 스트림을 닫지 않습니다.복사 후 스트림을 닫으려면 다음을 사용하십시오. FileCopyUtils 대신 수업 :

FileCopyUtils.copy(in, out);

JDK 방법을 사용하면 이 작업을 훨씬 더 쉽게 수행할 수 있는 방법은 없지만 Apocalisp가 이미 언급했듯이 이 아이디어를 가진 유일한 사람은 아닙니다.당신은 사용할 수 있습니다 IOUtils ~에서 자카르타 커먼즈 IO, 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();
    }

Commons Net의 Util 클래스를 사용하십시오.

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

가장 간단한 for 루프를 사용하는 방법은 다음과 같습니다.

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);
    }
}

IMHO의 최소한의 스니펫(길이 변수의 범위를 더 좁게 지정):

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

참고로 왜 더 많은 사람들이 for 루프 대신에 while 일부에서는 "불량" 스타일로 간주되는 할당 및 테스트 표현식을 사용합니다.

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

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

PipedInputStream과 PipedOutputStream은 서로 연결할 수 있으므로 유용할 수 있습니다.

또 다른 가능한 후보는 Guava I/O 유틸리티입니다.

http://code.google.com/p/guava-libraries/wiki/IO설명됨

나는 하나의 기능에 대해 또 다른 라이브러리를 추가하는 것보다 Guava가 내 프로젝트에 이미 엄청나게 유용하기 때문에 이것을 사용할 것이라고 생각했습니다.

나는 사용한다 BufferedInputStream 그리고 BufferedOutputStream 코드에서 버퍼링 의미를 제거하려면

try (OutputStream out = new BufferedOutputStream(...);
     InputStream in   = new BufferedInputStream(...))) {
  int ch;
  while ((ch = in.read()) != -1) {
    out.write(ch);
  }
}
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/객체 지향-input-output-in-cactuos.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){}
 }
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top