안드로이드에서 파일의 사본을 만드는 방법?


178

내 앱에서 특정 파일의 사본을 다른 이름으로 저장하고 싶습니다 (사용자에게서 얻음)

파일의 내용을 열고 다른 파일에 써야합니까?

가장 좋은 방법은 무엇입니까?


Java7 이전에는 대답이 그렇습니다. stackoverflow.com/questions/106770/… .
Paul Grime


이전 게시물
Deepak

답변:


327

파일을 복사하여 대상 경로에 저장하려면 아래 방법을 사용하십시오.

public static void copy(File src, File dst) throws IOException {
    InputStream in = new FileInputStream(src);
    try {
        OutputStream out = new FileOutputStream(dst);
        try {
            // Transfer bytes from in to out
            byte[] buf = new byte[1024];
            int len;
            while ((len = in.read(buf)) > 0) {
                out.write(buf, 0, len);
            }
        } finally {
            out.close();
        }
    } finally {
        in.close();
    }
}

API 19 이상에서는 Java 자동 자원 관리를 사용할 수 있습니다.

public static void copy(File src, File dst) throws IOException {
    try (InputStream in = new FileInputStream(src)) {
        try (OutputStream out = new FileOutputStream(dst)) {
            // Transfer bytes from in to out
            byte[] buf = new byte[1024];
            int len;
            while ((len = in.read(buf)) > 0) {
                out.write(buf, 0, len);
            }
        }
    }
}

8
감사합니다. 내 머리를 두드리고 나서 문제는 외부 저장소에 쓸 수있는 권한이 없다는 것을 알았습니다. 이제는 잘 작동합니다.
AS

8
파일을 복사하지 못하면 @ mohitum007에서 예외가 발생합니다. 메소드를 호출 할 때 try catch 블록을 사용하십시오.
Nima G

9
예외가 발생하면 가비지 수집 될 때까지 스트림이 닫히지 않으며 좋지 않습니다 . 에서 닫는 것을 고려하십시오 finally.
Pang

1
@격통. 네 말이 맞아 더 나쁜 것은 GC가 열린 파일 디스크립터를 닫지 않기 때문에 in / out.close ()를 호출해야합니다. 그렇지 않으면 기본 OS에 리소스 누수가 발생합니다. GC는 파일 디스크립터 또는 소켓과 같이 JVM 외부의 OS 자원을 닫을 수 없습니다. 그것들은 항상 프로그래밍 방식으로 finally 절에서 닫아야하거나 try-with-resource 새 구문을 사용해야합니다. docs.oracle.com/javase/tutorial/essential/exceptions/…
earizon

4
마지막으로 두 스트림을 모두 닫으십시오. Excepcion이 있으면 스트림 메모리가 수집되지 않습니다.
pozuelog

121

또는 FileChannel 을 사용 하여 파일을 복사 할 수 있습니다 . 그것은 많은 파일을 복사 할 때 빠른 바이트 복사 방법보다. 파일이 2GB보다 크면 사용할 수 없습니다.

public void copy(File src, File dst) throws IOException {
    FileInputStream inStream = new FileInputStream(src);
    FileOutputStream outStream = new FileOutputStream(dst);
    FileChannel inChannel = inStream.getChannel();
    FileChannel outChannel = outStream.getChannel();
    inChannel.transferTo(0, inChannel.size(), outChannel);
    inStream.close();
    outStream.close();
}

3
transferTo는 예외를 던질 수 있으며이 경우 스트림을 열린 채로 둡니다. 팡과 니마가 대답에 대해 언급 한 것처럼.
Viktor Brešan

또한 transferTo는 요청 된 총 금액을 전송할 것이라고 보장하지 않으므로 루프 내부에서 호출되어야합니다.
Viktor Brešan

귀하의 솔루션을 시도했지만 단계 java.io.FileNotFoundException: /sdcard/AppProj/IMG_20150626_214946.jpg: open failed: ENOENT (No such file or directory)에서 예외 로 인해 실패합니다 FileOutputStream outStream = new FileOutputStream(dst);. 내가 아는 텍스트에 따르면 파일이 존재하지 않으므로 파일을 확인하고 dst.mkdir();필요한 경우 전화 를 걸지만 여전히 도움이되지 않습니다. 나는 또한 확인을 시도 dst.canWrite();하고 돌아왔다 false. 이것이 문제의 원인 일 수 있습니까? 그리고 그렇습니다 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>.
Mike B.

1
@ ViktorBrešan API 19 이후에는 시험 시작시 인 / 아웃 스트림을 정의하여 Java 자동 리소스 관리를 사용할 수 있습니다.try ( FileInputStream inStream = new FileInputStream(src); FileOutputStream outStream = new FileOutputStream(dst) ) {
AlbertMarkovski

이 솔루션이 진행 상황을에 게시하도록 할 수있는 방법이 onProgressUpdate있습니까? 그래서 ProgressBar에 표시 할 수 있습니까? 수용 된 솔루션에서 while 루프의 진행 상황을 계산할 수 있지만 여기서 수행 방법을 볼 수는 없습니다.
George Bezerra

31

그것을위한 코 틀린 확장

fun File.copyTo(file: File) {
    inputStream().use { input ->
        file.outputStream().use { output ->
            input.copyTo(output)
        }
    }
}

가장 간결하면서도 유연한 답변입니다. 보다 간단한 답변은을 통해 열린 URI를 설명하지 못합니다 contentResolver.openInputStream(uri).
AjahnCharles

6
코 틀린은 사랑이고 코 틀린은 생명입니다!
Dev Aggarwal

17

이들은 나를 위해 잘 작동

public static void copyFileOrDirectory(String srcDir, String dstDir) {

    try {
        File src = new File(srcDir);
        File dst = new File(dstDir, src.getName());

        if (src.isDirectory()) {

            String files[] = src.list();
            int filesLength = files.length;
            for (int i = 0; i < filesLength; i++) {
                String src1 = (new File(src, files[i]).getPath());
                String dst1 = dst.getPath();
                copyFileOrDirectory(src1, dst1);

            }
        } else {
            copyFile(src, dst);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public static void copyFile(File sourceFile, File destFile) throws IOException {
    if (!destFile.getParentFile().exists())
        destFile.getParentFile().mkdirs();

    if (!destFile.exists()) {
        destFile.createNewFile();
    }

    FileChannel source = null;
    FileChannel destination = null;

    try {
        source = new FileInputStream(sourceFile).getChannel();
        destination = new FileOutputStream(destFile).getChannel();
        destination.transferFrom(source, 0, source.size());
    } finally {
        if (source != null) {
            source.close();
        }
        if (destination != null) {
            destination.close();
        }
    }
}

13

이것은 Android O (API 26)에서 간단합니다.

  @RequiresApi(api = Build.VERSION_CODES.O)
  public static void copy(File origin, File dest) throws IOException {
    Files.copy(origin.toPath(), dest.toPath());
  }

10

대답하기에는 너무 늦을 수 있지만 가장 편리한 방법은

FileUtils'에스

static void copyFile(File srcFile, File destFile)

예, 이것은 내가 한 일입니다

`

private String copy(String original, int copyNumber){
    String copy_path = path + "_copy" + copyNumber;
        try {
            FileUtils.copyFile(new File(path), new File(copy_path));
            return copy_path;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

`


20
FileUtils는 기본적으로 Android에 존재하지 않습니다.
Berga

2
: 그러나 이것과 더 많은 일을 할 아파치에 의해 만들어진 라이브러리있다 commons.apache.org/proper/commons-io/javadocs/api-2.5/org/...
알레산드로 Muzzi

7

Kotlin을 사용하면 훨씬 간단 해집니다.

 File("originalFileDir", "originalFile.name")
            .copyTo(File("newFileDir", "newFile.name"), true)

true또는 false대상 파일을 덮어 쓰기위한 것

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/java.io.-file/copy-to.html


파일이 갤러리 의도 Uri에서 온 경우 그렇게 간단하지 않습니다.
AjahnCharles

아래의 답변을 읽으십시오. "이 답변은 적극적으로 유해하며 투표권이 없습니다. Uri가 content : // 또는 기타 파일이 아닌 Uri 인 경우 실패합니다." (나는
공세를 했어요

5

복사하는 동안 오류가 발생하면 실제로 입력 / 출력 스트림을 닫는 솔루션이 있습니다. 이 솔루션은 스트림 닫기를 복사하고 처리하기 위해 Apache Commons IO IOUtils 방법을 사용합니다.

    public void copyFile(File src, File dst)  {
        InputStream in = null;
        OutputStream out = null;
        try {
            in = new FileInputStream(src);
            out = new FileOutputStream(dst);
            IOUtils.copy(in, out);
        } catch (IOException ioe) {
            Log.e(LOGTAG, "IOException occurred.", ioe);
        } finally {
            IOUtils.closeQuietly(out);
            IOUtils.closeQuietly(in);
        }
    }

그것은 간단 해 보인다
Serg Burlaka

2

kotlin에서, 단지 :

val fileSrc : File = File("srcPath")
val fileDest : File = File("destPath")

fileSrc.copyTo(fileDest)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.