एंड्राइड में फाइल की कॉपी कैसे बनाये?


178

अपने ऐप में मैं एक निश्चित फ़ाइल की एक कॉपी को एक अलग नाम से सहेजना चाहता हूं (जो मुझे उपयोगकर्ता से मिलती है)

क्या मुझे वास्तव में फ़ाइल की सामग्री को खोलने और इसे किसी अन्य फ़ाइल में लिखने की आवश्यकता है?

ऐसा करने का सबसे अच्छा तरीका क्या है?


Java7 से पहले, मुझे लगता है कि इसका जवाब हां में है। stackoverflow.com/questions/106770/…
पॉल ग्राइम


पुराने पोस्ट की
दीपक

जवाबों:


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

एपीआई 19+ पर आप जावा स्वचालित संसाधन प्रबंधन का उपयोग कर सकते हैं:

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
धन्यवाद। मेरे सिर को पीटने के बाद मैंने पाया कि समस्या बाहरी भंडारण को लिखने की अनुमति नहीं थी। अब यह ठीक काम करता है।
के रूप में

8
@ mohitum007 यदि फ़ाइल कॉपी करने में विफल रहती है तो एक अपवाद फेंक दिया जाता है। विधि को कॉल करते समय एक कोशिश पकड़ ब्लॉक का उपयोग करें।
नीमा जी

9
यदि एक अपवाद को फेंक दिया जाता है, तो धाराएं तब तक बंद नहीं होंगी जब तक वे कचरा एकत्र नहीं करते हैं, और यह अच्छा नहीं है । उन्हें बंद करने पर विचार करें finally
पंग

1
@Pang। तुम सही हो। क्या बुरा है, में / out.close () को बुलाया जाना चाहिए या अन्यथा अंतर्निहित ओएस में एक संसाधन रिसाव होगा, क्योंकि जीसी कभी भी खुले फ़ाइल विवरणों को बंद नहीं करेगा। GC, JVM जैसे फ़ाइल-डिस्क्रिप्टर या सॉकेट के लिए बाहरी ओएस संसाधनों को बंद नहीं कर सकता है। उन्हें हमेशा प्रोग्राम के अंत में अंतिम रूप से बंद किया जाना चाहिए या कोशिश के साथ-साथ संसाधन नए सिंटैक्स का उपयोग करना चाहिए: docs.oracle.com/javase/tutorial/essential/exception//
ईरानी

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 एक अपवाद फेंक सकता है और उस स्थिति में आप धाराएँ खुली छोड़ रहे हैं। जैसे पैंग और नीमा ने स्वीकृत उत्तर में टिप्पणी की।
विक्टर ब्रेजन

इसके अलावा, ट्रांसफ़ोटो को लूप के अंदर बुलाया जाना चाहिए क्योंकि यह गारंटी नहीं देता है कि यह अनुरोधित कुल राशि को स्थानांतरित कर देगा।
विक्टर ब्रेजन

मैंने आपके समाधान की कोशिश की और यह कदम 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"/>
माइक बी।

1
@ VistaBrešan एपीआई 19 के बाद आप अपनी कोशिश के उद्घाटन में इन और आउट स्ट्रीम को परिभाषित करके जावा स्वचालित संसाधन प्रबंधन का उपयोग कर सकते हैंtry ( FileInputStream inStream = new FileInputStream(src); FileOutputStream outStream = new FileOutputStream(dst) ) {
AlbertMarkovski

क्या इस समाधान को बनाने के लिए इसकी प्रगति को प्रकाशित करने का कोई तरीका है onProgressUpdate, इसलिए मैं इसे प्रोग्रेसबार में दिखा सकता हूं? स्वीकृत समाधान में मैं लूप में प्रगति की गणना कर सकता हूं, लेकिन मैं यह नहीं देख सकता कि यहां कैसे करना है।
जॉर्ज बेज़रा

31

इसके लिए कोटलीन एक्सटेंशन

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

यह सबसे संक्षिप्त अभी तक लचीला जवाब है। यूआरआई के माध्यम से खोले गए सरल उत्तर विफल हो जाते हैं contentResolver.openInputStream(uri)
अजहरचर्ल्स

6
कोटलिन प्यार है, कोटलिन जीवन है!
देव अग्रवाल

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 में मौजूद नहीं है।
बर्गा

2
लेकिन अपाचे द्वारा बनाई गई एक लाइब्रेरी है जो ऐसा करती है और अधिक: commons.apache.org/proper/commons-io/javadocs/api-2.5/org/……
Alessandro Muzzi

7

कोटलिन के साथ अब बहुत सरल:

 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


इतना आसान नहीं है अगर आपकी फ़ाइल एक गैलरी इरादे उरी से आती है।
अजानचर्ल्स

उस उत्तर के नीचे दिए गए टिप्पणियों को पढ़ें: "यह उत्तर सक्रिय रूप से हानिकारक है और इसे प्राप्त होने वाले वोटों के लायक नहीं है। यह विफल रहता है यदि उड़ी एक सामग्री है: // या कोई अन्य गैर-फाइल उड़ी।" (मैंने उत्थान किया - मैं सिर्फ यह स्पष्ट करना चाहता था कि यह सिल्वर-बुलेट नहीं है)
AjahnCharles

5

यहां एक समाधान है जो वास्तव में इनपुट / आउटपुट धाराओं को बंद कर देता है अगर नकल करते समय कोई त्रुटि होती है। यह समाधान अपाचे कॉमन्स 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);
        }
    }

यह सरल लग रहा है
सर्ग बरलाका

2

कोटलिन में, बस:

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

fileSrc.copyTo(fileDest)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.