एक फ़ाइल को एक सुरक्षित, सुरक्षित और कुशल तरीके से कॉपी करें


305

मैं फ़ाइल (बाइनरी या टेक्स्ट) की प्रतिलिपि बनाने के लिए एक अच्छा तरीका खोजता हूं। मैंने कई नमूने लिखे हैं, हर कोई काम करता है। लेकिन मैं अनुभवी प्रोग्रामरों की राय सुनना चाहता हूं।

मुझे अच्छे उदाहरण याद आ रहे हैं और एक ऐसा तरीका खोज रहे हैं जो C ++ के साथ काम करता है।

एएनएसआई-सी-तरफा

#include <iostream>
#include <cstdio>    // fopen, fclose, fread, fwrite, BUFSIZ
#include <ctime>
using namespace std;

int main() {
    clock_t start, end;
    start = clock();

    // BUFSIZE default is 8192 bytes
    // BUFSIZE of 1 means one chareter at time
    // good values should fit to blocksize, like 1024 or 4096
    // higher values reduce number of system calls
    // size_t BUFFER_SIZE = 4096;

    char buf[BUFSIZ];
    size_t size;

    FILE* source = fopen("from.ogv", "rb");
    FILE* dest = fopen("to.ogv", "wb");

    // clean and more secure
    // feof(FILE* stream) returns non-zero if the end of file indicator for stream is set

    while (size = fread(buf, 1, BUFSIZ, source)) {
        fwrite(buf, 1, size, dest);
    }

    fclose(source);
    fclose(dest);

    end = clock();

    cout << "CLOCKS_PER_SEC " << CLOCKS_PER_SEC << "\n";
    cout << "CPU-TIME START " << start << "\n";
    cout << "CPU-TIME END " << end << "\n";
    cout << "CPU-TIME END - START " << end - start << "\n";
    cout << "TIME(SEC) " << static_cast<double>(end - start) / CLOCKS_PER_SEC << "\n";

    return 0;
}

POSIX-WAY (K & R इसका उपयोग "द C प्रोग्रामिंग लैंग्वेज" में करते हैं, अधिक निम्न-स्तर)

#include <iostream>
#include <fcntl.h>   // open
#include <unistd.h>  // read, write, close
#include <cstdio>    // BUFSIZ
#include <ctime>
using namespace std;

int main() {
    clock_t start, end;
    start = clock();

    // BUFSIZE defaults to 8192
    // BUFSIZE of 1 means one chareter at time
    // good values should fit to blocksize, like 1024 or 4096
    // higher values reduce number of system calls
    // size_t BUFFER_SIZE = 4096;

    char buf[BUFSIZ];
    size_t size;

    int source = open("from.ogv", O_RDONLY, 0);
    int dest = open("to.ogv", O_WRONLY | O_CREAT /*| O_TRUNC/**/, 0644);

    while ((size = read(source, buf, BUFSIZ)) > 0) {
        write(dest, buf, size);
    }

    close(source);
    close(dest);

    end = clock();

    cout << "CLOCKS_PER_SEC " << CLOCKS_PER_SEC << "\n";
    cout << "CPU-TIME START " << start << "\n";
    cout << "CPU-TIME END " << end << "\n";
    cout << "CPU-TIME END - START " << end - start << "\n";
    cout << "TIME(SEC) " << static_cast<double>(end - start) / CLOCKS_PER_SEC << "\n";

    return 0;
}

KISS-सी ++ - Streambuffer-तरफा

#include <iostream>
#include <fstream>
#include <ctime>
using namespace std;

int main() {
    clock_t start, end;
    start = clock();

    ifstream source("from.ogv", ios::binary);
    ofstream dest("to.ogv", ios::binary);

    dest << source.rdbuf();

    source.close();
    dest.close();

    end = clock();

    cout << "CLOCKS_PER_SEC " << CLOCKS_PER_SEC << "\n";
    cout << "CPU-TIME START " << start << "\n";
    cout << "CPU-TIME END " << end << "\n";
    cout << "CPU-TIME END - START " <<  end - start << "\n";
    cout << "TIME(SEC) " << static_cast<double>(end - start) / CLOCKS_PER_SEC << "\n";

    return 0;
}

कॉपी-एल्गोरिथ्म-सी ++ - रास्ता

#include <iostream>
#include <fstream>
#include <ctime>
#include <algorithm>
#include <iterator>
using namespace std;

int main() {
    clock_t start, end;
    start = clock();

    ifstream source("from.ogv", ios::binary);
    ofstream dest("to.ogv", ios::binary);

    istreambuf_iterator<char> begin_source(source);
    istreambuf_iterator<char> end_source;
    ostreambuf_iterator<char> begin_dest(dest); 
    copy(begin_source, end_source, begin_dest);

    source.close();
    dest.close();

    end = clock();

    cout << "CLOCKS_PER_SEC " << CLOCKS_PER_SEC << "\n";
    cout << "CPU-TIME START " << start << "\n";
    cout << "CPU-TIME END " << end << "\n";
    cout << "CPU-TIME END - START " <<  end - start << "\n";
    cout << "TIME(SEC) " << static_cast<double>(end - start) / CLOCKS_PER_SEC << "\n";

    return 0;
}

स्वयं-बफर-सी ++ - रास्ता

#include <iostream>
#include <fstream>
#include <ctime>
using namespace std;

int main() {
    clock_t start, end;
    start = clock();

    ifstream source("from.ogv", ios::binary);
    ofstream dest("to.ogv", ios::binary);

    // file size
    source.seekg(0, ios::end);
    ifstream::pos_type size = source.tellg();
    source.seekg(0);
    // allocate memory for buffer
    char* buffer = new char[size];

    // copy file    
    source.read(buffer, size);
    dest.write(buffer, size);

    // clean up
    delete[] buffer;
    source.close();
    dest.close();

    end = clock();

    cout << "CLOCKS_PER_SEC " << CLOCKS_PER_SEC << "\n";
    cout << "CPU-TIME START " << start << "\n";
    cout << "CPU-TIME END " << end << "\n";
    cout << "CPU-TIME END - START " <<  end - start << "\n";
    cout << "TIME(SEC) " << static_cast<double>(end - start) / CLOCKS_PER_SEC << "\n";

    return 0;
}

LINUX-WAY // को कर्नेल> = 2.6.33 की आवश्यकता है

#include <iostream>
#include <sys/sendfile.h>  // sendfile
#include <fcntl.h>         // open
#include <unistd.h>        // close
#include <sys/stat.h>      // fstat
#include <sys/types.h>     // fstat
#include <ctime>
using namespace std;

int main() {
    clock_t start, end;
    start = clock();

    int source = open("from.ogv", O_RDONLY, 0);
    int dest = open("to.ogv", O_WRONLY | O_CREAT /*| O_TRUNC/**/, 0644);

    // struct required, rationale: function stat() exists also
    struct stat stat_source;
    fstat(source, &stat_source);

    sendfile(dest, source, 0, stat_source.st_size);

    close(source);
    close(dest);

    end = clock();

    cout << "CLOCKS_PER_SEC " << CLOCKS_PER_SEC << "\n";
    cout << "CPU-TIME START " << start << "\n";
    cout << "CPU-TIME END " << end << "\n";
    cout << "CPU-TIME END - START " <<  end - start << "\n";
    cout << "TIME(SEC) " << static_cast<double>(end - start) / CLOCKS_PER_SEC << "\n";

    return 0;
}

वातावरण

  • GNU / LINUX (Archlinux)
  • कर्नेल ३.३
  • GLIBC-2.15, LIBSTDC ++ 4.7 (GCC-LIBS), GCC 4.7, Coreutils 8.16
  • RUNLEVEL 3 (बहुउपयोगकर्ता, नेटवर्क, टर्मिनल, कोई GUI) का उपयोग करना
  • SSD-Postville 80 GB, 50% तक भरा
  • एक 270 एमबी ओजीजी-वीडियो-कॉपी की प्रतिलिपि बनाएँ

प्रजनन करने कि प्रक्रिया

 1. $ rm from.ogg
 2. $ reboot                           # kernel and filesystem buffers are in regular
 3. $ (time ./program) &>> report.txt  # executes program, redirects output of program and append to file
 4. $ sha256sum *.ogv                  # checksum
 5. $ rm to.ogg                        # remove copy, but no sync, kernel and fileystem buffers are used
 6. $ (time ./program) &>> report.txt  # executes program, redirects output of program and append to file

परिणाम (CPU समय का उपयोग)

Program  Description                 UNBUFFERED|BUFFERED
ANSI C   (fread/frwite)                 490,000|260,000  
POSIX    (K&R, read/write)              450,000|230,000  
FSTREAM  (KISS, Streambuffer)           500,000|270,000 
FSTREAM  (Algorithm, copy)              500,000|270,000
FSTREAM  (OWN-BUFFER)                   500,000|340,000  
SENDFILE (native LINUX, sendfile)       410,000|200,000  

फ़ाइलें बदलना नहीं है।
sha256sum समान परिणाम प्रिंट करते हैं।
वीडियो फ़ाइल अभी भी खेलने योग्य है।

प्रशन

  • आप किस विधि को प्राथमिकता देंगे?
  • क्या आप बेहतर उपाय जानते हैं?
  • क्या आपको मेरे कोड में कोई गलतियाँ दिखती हैं?
  • क्या आप समाधान से बचने का एक कारण जानते हैं?

  • FSTREAM (KISS, Streambuffer)
    मैं वास्तव में इस तरह, क्योंकि यह वास्तव में छोटे और सरल है। जहां तक ​​मुझे पता है कि ऑपरेटर << rdbuf () के लिए अतिभारित है और कुछ भी परिवर्तित नहीं करता है। सही बात?

धन्यवाद

अद्यतन 1
मैंने उस तरह से सभी नमूनों में स्रोत को बदल दिया, कि घड़ी के मापक में फ़ाइल डिस्क्रिप्टर का खुला और बंद होना शामिल है । उनके स्रोत कोड में कोई अन्य महत्वपूर्ण बदलाव नहीं हैं। परिणाम नहीं बदले! मैंने अपने परिणामों को दोबारा जांचने के लिए समय का उपयोग किया ।

अद्यतन 2
एएनएसआई सी नमूना बदल गया: लूप की स्थिति किसी भी लंबे समय तक फ़ॉफ़ () नहीं कहती है इसके बजाय मैं फ़्रेड ले गया () हालत में। ऐसा लगता है, कोड अब 10,000 घड़ियों को तेजी से चलाता है।

माप बदल गया: पूर्व परिणाम हमेशा बफ़र किए गए थे, क्योंकि मैंने पुरानी कमांड लाइन rm to.ogv && सिंक और& time ./program को प्रत्येक प्रोग्राम के लिए कुछ समय में दोहराया था । अब मैं हर प्रोग्राम के लिए सिस्टम को रिबूट करता हूं। असंबद्ध परिणाम नए हैं और कोई आश्चर्य नहीं दिखाते हैं। असंबद्ध परिणाम वास्तव में नहीं बदले।

यदि मैं पुरानी प्रति नहीं हटाता हूं, तो प्रोग्राम अलग-अलग प्रतिक्रिया देते हैं। किसी मौजूदा फ़ाइल को अधिलेखित करना POSIX और SENDFILE के साथ बफ़र किया गया है, अन्य सभी प्रोग्राम धीमे हैं। हो सकता है कि विकल्प काट - छाँट या बनाने से इस व्यवहार पर असर पड़े। लेकिन एक ही कॉपी के साथ मौजूदा फ़ाइलों को अधिलेखित करना वास्तविक दुनिया का उपयोग-मामला नहीं है।

प्रतिलिपि cp के साथ प्रदर्शन करने में 0.44 सेकंड लगते हैं, 0. 0.30 सेकंड बिना बफ़र किए हुए। तो POSIX नमूने की तुलना में cp थोड़ा धीमा है। मेरे लिए ठीक लग रहा है।

हो सकता है कि मैं mmap () और copy_file()बूस्ट :: filesystem के नमूने और परिणाम भी जोड़ दूं

अपडेट 3
मैंने इसे ब्लॉग पेज पर भी डाल दिया है और इसे थोड़ा बढ़ा दिया है। जिसमें स्प्लिस () शामिल है , जो लिनक्स कर्नेल से एक निम्न-स्तरीय फ़ंक्शन है। शायद जावा के साथ अधिक नमूने का पालन करेंगे। http://www.ttyhoney.com/blog/?page_id=69


5
fstreamनिश्चित रूप से फ़ाइल संचालन के लिए एक अच्छा विकल्प है।
क्रिस


28
आप आलसी तरीके को भूल गए: सिस्टम ("cp from.ogv to.ogv");
fbafelipe

3
#include <copyfile.h> copyfile(const char *from, const char *to, copyfile_state_t state, copyfile_flags_t flags);
मार्टिन यॉर्क

3
इतनी देर में चिल करने के लिए क्षमा करें, लेकिन मैं इनमें से किसी को भी 'सुरक्षित' नहीं बताऊंगा, क्योंकि उनके पास कोई त्रुटि नहीं है।
रिचर्ड केटलवेल

जवाबों:


259

एक फ़ाइल को एक तरह से कॉपी करें:

#include <fstream>

int main()
{
    std::ifstream  src("from.ogv", std::ios::binary);
    std::ofstream  dst("to.ogv",   std::ios::binary);

    dst << src.rdbuf();
}

यह पढ़ने में इतना सरल और सहज है कि यह अतिरिक्त लागत के लायक है। यदि हम इसे बहुत कुछ कर रहे थे, तो फ़ाइल सिस्टम पर ओएस कॉल पर वापस आना बेहतर होगा। मुझे यकीन boostहै कि इसकी फाइलसिस्टम क्लास में एक कॉपी फाइल विधि है।

फ़ाइल सिस्टम के साथ बातचीत करने के लिए एक सी विधि है:

#include <copyfile.h>

int
copyfile(const char *from, const char *to, copyfile_state_t state, copyfile_flags_t flags);

28
copyfileपोर्टेबल नहीं है; मुझे लगता है कि यह मैक ओएस एक्स के लिए विशिष्ट है। यह निश्चित रूप से लिनक्स पर मौजूद नहीं है। boost::filesystem::copy_fileशायद मूल फ़ाइल सिस्टम के माध्यम से किसी फ़ाइल को कॉपी करने का सबसे पोर्टेबल तरीका है।
माइक सेमोर

4
@MikeSeymour: copyfile () बीएसडी एक्सटेंशन लगता है।
मार्टिन यॉर्क

10
@ duedl0r: नहीं। वस्तुओं में विध्वंसक होते हैं। धाराओं के लिए विध्वंसक स्वचालित रूप से करीब () कहता है। codereview.stackexchange.com/q/540/507
मार्टिन

11
@ duedl0r: हाँ। लेकिन यह कहने जैसा है कि "अगर सूरज डूबता है"। आप वास्तव में तेजी से पश्चिम चला सकते हैं और आप अपने दिन को थोड़ा लंबा कर सकते हैं लेकिन सूर्य अस्त होने वाला है। जब तक आपके पास बग और लीक मेमोरी नहीं है (यह गुंजाइश से बाहर निकल जाएगा)। लेकिन चूंकि यहां कोई डायनेमिक मेमोरी मैनेजमेंट नहीं है इसलिए रिसाव नहीं हो सकता है और वे दायरे से बाहर हो जाएंगे (ठीक उसी तरह जैसे सूरज अस्त होगा)।
मार्टिन

6
फिर इसे {} स्कोप ब्लॉक
पॉल्म

62

C ++ 17 के साथ एक फ़ाइल को कॉपी करने का मानक तरीका <filesystem>हेडर और उपयोग सहित होगा :

bool copy_file( const std::filesystem::path& from,
                const std::filesystem::path& to);

bool copy_file( const std::filesystem::path& from,
                const std::filesystem::path& to,
                std::filesystem::copy_options options);

पहला रूप दूसरे के बराबर है जिसका copy_options::noneउपयोग विकल्प के रूप में किया गया है (यह भी देखें copy_file)।

filesystemपुस्तकालय के रूप में मूल रूप से विकसित किया गया था boost.filesystemऔर अंत में आईएसओ सेल्सियस तक ++ सी ++ 17 के रूप में विलय कर दिया।


2
डिफ़ॉल्ट तर्क के साथ एक भी फ़ंक्शन क्यों नहीं है, जैसे bool copy_file( const std::filesystem::path& from, const std::filesystem::path& to, std::filesystem::copy_options options = std::filesystem::copy_options::none);?
जेपेसन

2
@ जेसेसेन मैं इस बारे में निश्चित नहीं हूं। शायद यह वास्तव में कोई फर्क नहीं पड़ता
manlio

@ जेपेसन मानक पुस्तकालय में, स्वच्छ कोड सर्वोपरि है। अधिभार (डिफ़ॉल्ट मापदंडों के साथ एक फ़ंक्शन के विपरीत) होने से प्रोग्रामर का इरादा अधिक स्पष्ट हो जाता है।
Marc.2377

@Peter अब यह स्वीकार किया जाना चाहिए कि C ++ 17 उपलब्ध है।
मार्टिन यॉर्क

21

बहुत अधिक!

"ANSI C" रास्ता बफर बेमानी है, क्योंकि FILEपहले से ही बफर है। (इस आंतरिक बफर का आकार BUFSIZवास्तव में परिभाषित करता है।)

"OWN-BUFFER-C ++ - WAY" धीमा हो जाएगा क्योंकि यह गुजरता है fstream, जो बहुत सारे आभासी प्रेषण करता है, और फिर से आंतरिक बफ़र्स या प्रत्येक स्ट्रीम ऑब्जेक्ट को बनाए रखता है। ("COPY-ALGORITHM-C ++ - WAY" को इसका नुकसान नहीं होता है, क्योंकि streambuf_iteratorक्लास स्ट्रीम स्ट्रीम को बायपास कर देती है।)

मैं "COPY-ALGORITHM-C ++ - WAY" पसंद करता हूं, लेकिन एक निर्माण के बिना fstream, बस नंगे std::filebufउदाहरण बनाते हैं जब कोई वास्तविक स्वरूपण की आवश्यकता नहीं होती है।

कच्चे प्रदर्शन के लिए, आप POSIX फ़ाइल विवरणकों को नहीं हरा सकते। यह किसी भी मंच पर बदसूरत लेकिन पोर्टेबल और तेज है।

लिनक्स तरीका अविश्वसनीय रूप से तेज़ प्रतीत होता है - शायद ओएस ने I / O समाप्त होने से पहले फ़ंक्शन को वापस आने दिया? किसी भी मामले में, यह कई अनुप्रयोगों के लिए पर्याप्त पोर्टेबल नहीं है।

संपादित करें : आह, "देशी लिनक्स" इंटरलेन्डिंग रीडिंग द्वारा प्रदर्शन में सुधार कर सकता है और अतुल्यकालिक I / O के साथ लिख सकता है। आज्ञा देना ढेर को डिस्क चालक को यह तय करने में मदद कर सकता है कि कब तलाश करना सबसे अच्छा है। आप तुलना के लिए Asio या pthreads की कोशिश कर सकते हैं। के रूप में के लिए "पीओएसआईएक्स फ़ाइल डिस्क्रिप्टर को हरा नहीं सकते" ... यह सच है कि यदि आप डेटा के साथ कुछ भी कर रहे हैं, न कि केवल आंख मूंदकर नकल कर रहे हैं।


एएनएसआई सी: लेकिन मुझे फंक्शन को फ़्रेड / राइटराइट एक आकार देना होगा? pubs.opengroup.org/onlinepubs/9699919799/toc.htm
पीटर

@PeterWeber खैर, हां, यह सच है कि BUFSIZ किसी भी तरह से एक अच्छा मूल्य है, और शायद एक समय में एक या "बस कुछ" पात्रों के सापेक्ष चीजों को गति देगा। वैसे भी, प्रदर्शन माप यह बताता है कि यह किसी भी मामले में सबसे अच्छा तरीका नहीं है।
पोटाटोस्वाटर

1
मुझे इसकी गहरी समझ नहीं है, इसलिए मुझे धारणाओं और विचारों से सावधान रहना चाहिए। लिनक्स-वे Kernelspace afaik में चलता है। यह कर्नेलस्पेस और उपयोगकर्तास्पेस के बीच धीमी गति से स्विच करने से बचना चाहिए? कल मैं फिर से Sendfile के मैनपेज पर एक नज़र डालूंगा। कुछ समय पहले लिनुस टॉर्वाल्ड्स ने कहा कि उन्हें भारी नौकरियों के लिए यूजरस्पेस-फाइलसिस्टम पसंद नहीं है। हो सकता है कि सेंडफाइल उनके विचार के लिए एक सकारात्मक उदाहरण हो?
पीटर

5
" sendfile()एक फ़ाइल डिस्क्रिप्टर और दूसरे के बीच डेटा की प्रतिलिपि बनाता है। क्योंकि यह कॉपी कर्नेल के भीतर किया जाता है, sendfile()के संयोजन से अधिक कुशल है , read(2)और write(2)जिसके लिए उपयोगकर्ता स्थान से डेटा स्थानांतरित करना आवश्यक होगा।": kernel.org/doc/man-pages। /online/pages/man2/sendfile.2.html
मैक्स Lybbert

1
क्या आप कच्ची filebufवस्तुओं का उपयोग करने का एक उदाहरण पोस्ट कर सकते हैं?
केरेक एसबी

14

मैं बहुत महत्वपूर्ण नोट करना चाहता हूं कि Sendfile () का उपयोग करके LINUX विधि में एक बड़ी समस्या यह है कि यह आकार में 2GB से अधिक फ़ाइलों की प्रतिलिपि नहीं बना सकता है! मैंने इसे इस प्रश्न के बाद लागू किया था और समस्याओं से जूझ रहा था क्योंकि मैं इसका उपयोग HDF5 फ़ाइलों की प्रतिलिपि बनाने के लिए कर रहा था जो आकार में कई जीबी थीं।

http://man7.org/linux/man-pages/man2/sendfile.2.html

Sendfile () सबसे अधिक 0x7ffff000 (2,147,479,552) बाइट्स में ट्रांसफर करेगा, बाइट्स की संख्या वास्तव में ट्रांसफर हो जाएगी। (यह 32-बिट और 64-बिट सिस्टम दोनों पर सच है।)


1
Sendfile64 () में एक ही समस्या है?
ग्रेवॉल्फ

1
@Paladin ऐसा लगता है कि Sendfile64 को इस सीमा के आसपास पाने के लिए विकसित किया गया था। मैन पेज से: "" "ओरिजिनल लिनक्स सेंडफाइल () सिस्टम कॉल को बड़े फाइल ऑफ़सेट्स को संभालने के लिए डिज़ाइन नहीं किया गया था। नतीजतन, ऑफ़सेट तर्क के लिए एक व्यापक प्रकार के साथ लिनक्स 2.4 ने सेंडफिले 64 () को जोड़ा। ग्लिफ़ फ़िफ़ाइल () आवरण फ़ंक्शन। पारदर्शी रूप से कर्नेल अंतर से संबंधित है। ""
rveale

sendfile64 में वही मुद्दा है जो लगता है। हालाँकि ऑफ़सेट प्रकार off64_tका उपयोग बड़ी फ़ाइलों को कॉपी करने के लिए लूप का उपयोग करने की अनुमति देता है जैसा कि जुड़े हुए प्रश्न के उत्तर में दिखाया गया है
pcworld

यह आदमी में घिनौना है: 'ध्यान दें कि Sendfile () के लिए एक सफल कॉल अनुरोध की तुलना में कम बाइट लिख सकता है; यदि कॉल अनसुनी बाइट्स होती है, तो कॉल करने वाले को वापस लेने के लिए तैयार रहना चाहिए। ' जब तक पूरी कॉपी नहीं हो जाती है तब तक sendfile या sendfile64 को लूप के भीतर बुलाया जा सकता है।
फिलिप्पे लार्डी

2

Qt में फ़ाइलों की प्रतिलिपि बनाने की एक विधि है:

#include <QFile>
QFile::copy("originalFile.example","copiedFile.example");

ध्यान दें कि यह आप के लिए है का उपयोग करने के क्यूटी स्थापित (निर्देश यहाँ ) और अपनी परियोजना में शामिल है (यदि आप Windows का उपयोग कर रहे हैं और आप कोई व्यवस्थापक नहीं हैं, तो आप क्यूटी डाउनलोड कर सकते हैं यहाँ के बजाय)। इसका उत्तर भी देखें ।


1
QFile::copyयह 4k बफरिंग के कारण हास्यास्पद रूप से धीमा है ।
निकोलस होल्टहॉस 18

1
के नए संस्करणों में धीमापन तय किया गया है Qt। मैं उपयोग कर रहा हूं 5.9.2और मूल कार्यान्वयन के साथ गति बराबर है। Btw। स्रोत कोड पर एक नज़र डालते हुए, Qt वास्तव में मूल कार्यान्वयन को कहते हैं।
वीके

1

बढ़ावा देने वालों के लिए:

boost::filesystem::path mySourcePath("foo.bar");
boost::filesystem::path myTargetPath("bar.foo");

// Variant 1: Overwrite existing
boost::filesystem::copy_file(mySourcePath, myTargetPath, boost::filesystem::copy_option::overwrite_if_exists);

// Variant 2: Fail if exists
boost::filesystem::copy_file(mySourcePath, myTargetPath, boost::filesystem::copy_option::fail_if_exists);

ध्यान दें कि बढ़ावा देने के लिए :: फ़ाइल सिस्टम :: पथ यूनिकोड के लिए wpath के रूप में भी उपलब्ध है । और यह कि आप भी इस्तेमाल कर सकते हैं

using namespace boost::filesystem

अगर आपको वे लंबे प्रकार के नाम पसंद नहीं हैं


बूस्ट की फाइलसिस्टम लाइब्रेरी उन अपवादों में से एक है जिनके लिए इसे संकलित करने की आवश्यकता होती है। सिर्फ आपकी जानकारी के लिए!
साइमन

0

मुझे पूरा यकीन नहीं है कि फ़ाइल की प्रतिलिपि बनाने का एक "अच्छा तरीका" क्या है, लेकिन "अच्छा" मानने का अर्थ है "तेज़", मैं विषय को थोड़ा चौड़ा कर सकता हूं।

वर्तमान ऑपरेटिंग सिस्टम लंबे समय से मिल फाइल कॉपी के चलाने से निपटने के लिए अनुकूलित किया गया है। कोड का कोई चतुर बिट हरा देगा। यह संभव है कि आपकी कॉपी तकनीकों के कुछ प्रकार कुछ परीक्षण परिदृश्य में तेजी से साबित होंगे, लेकिन वे अन्य मामलों में सबसे खराब संभावना होगी।

आमतौर पर, sendfile फ़ंक्शन संभवतः लिखने से पहले वापस आ गया है, इस प्रकार बाकी की तुलना में तेज़ होने का आभास देता है। मैंने कोड नहीं पढ़ा है, लेकिन यह निश्चित रूप से है क्योंकि यह समय के लिए अपने स्वयं के समर्पित बफर, ट्रेडिंग मेमोरी को आवंटित करता है। और यही कारण है कि यह 2Gb से बड़ी फ़ाइलों के लिए काम नहीं करेगा।

जब तक आप फ़ाइलों की एक छोटी संख्या के साथ काम कर रहे हैं, सब कुछ विभिन्न बफ़र्स के अंदर होता है (सी ++ रनटाइम का पहला यदि आप उपयोग करते हैं iostream, तो ओएस आंतरिक वाले, जाहिरा तौर पर एक फ़ाइल के आकार के अतिरिक्त बफर के मामले मेंsendfile )। वास्तविक भंडारण मीडिया को केवल तब तक एक्सेस किया जाता है जब एक हार्ड डिस्क को स्पिन करने की परेशानी के लायक पर्याप्त डेटा ले जाया गया हो।

मुझे लगता है कि आप विशिष्ट मामलों में प्रदर्शन में थोड़ा सुधार कर सकते हैं। मेरे सर के ऊपर से चला गया:

  • यदि आप एक ही डिस्क पर एक बड़ी फ़ाइल की प्रतिलिपि बना रहे हैं, तो OS से बड़े बफर का उपयोग करने से चीजों में थोड़ा सुधार हो सकता है (लेकिन हम शायद यहां गीगाबाइट के बारे में बात कर रहे हैं)।
  • यदि आप एक ही फाइल को दो अलग-अलग भौतिक स्थलों पर कॉपी करना चाहते हैं, तो आप दो copy_fileक्रमिक रूप से कॉल करने की तुलना में एक साथ तीन फ़ाइलों को खोलना संभवत: तेजी से खोलेंगे (हालांकि आप शायद ही अंतर को देखेंगे जब तक कि फ़ाइल ओएस कैश में फिट हो जाती है)
  • यदि आप HDD पर बहुत सारी छोटी फ़ाइलों के साथ काम कर रहे हैं, तो आप उन्हें समय की मांग को कम करने के लिए बैचों में पढ़ना चाह सकते हैं (हालांकि ओएस पहले से ही निर्देशिका प्रविष्टियों को पागल और छोटी फ़ाइलों की तरह से बचने के लिए नाटकीय रूप से डिस्क बैंडविड्थ को कम कर देगा)।

लेकिन यह सब एक सामान्य उद्देश्य फ़ाइल कॉपी फ़ंक्शन के दायरे से बाहर है।

तो मेरे यकीनन अनुभवी प्रोग्रामर की राय में, एक C ++ फ़ाइल कॉपी को C ++ 17 file_copyसमर्पित फ़ंक्शन का उपयोग करना चाहिए , जब तक कि उस संदर्भ के बारे में अधिक जानकारी न हो जहां फ़ाइल कॉपी होती है और OS को आउटसोर्स करने के लिए कुछ चतुर रणनीतियों को तैयार किया जा सकता है।

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