ファイルのコピーは、プログラミングにおける一般的なタスクです。このタスクには、健全性と効率性の両方を持って取り組むことが不可欠です。この記事では、C でファイルをコピーするためのさまざまな手法を検討し、その長所と短所について説明します。とりわけ、標準 C 関数、POSIX 関数、C ストリーム バッファーについて説明します。
このアプローチでは、C 標準ライブラリ関数 fread を使用します。 () および fwrite() を使用して、ブロック内のデータを読み書きします。低レベルの制御を提供しますが、明示的なバッファ管理が必要で、冗長になる可能性があります。
// ANSI-C-WAY #include <stdio.h> // fopen(), fclose(), fread(), fwrite(), BUFSIZ #include <cstdio> // size_t using namespace std; int main() { // Define buffer size (BUFSIZE default is 8192 bytes) const size_t BUFFER_SIZE = 4096; char buf[BUFFER_SIZE]; size_t size; FILE* source = fopen("from.ogv", "rb"); FILE* dest = fopen("to.ogv", "wb"); while (size = fread(buf, 1, BUFFER_SIZE, source)) { fwrite(buf, 1, size, dest); } fclose(source); fclose(dest); return 0; }
このアプローチは、POSIX read( ) および write() 関数を使用して、ANSI C アプローチよりもファイル操作をより詳細に制御できます。これにより、より大きなファイルを処理し、エラーをより細心の注意を払って処理する機能が提供されます。
// POSIX-WAY #include <fcntl.h> // open() #include <unistd.h> // read(), write(), close() #include <stdio.h> // BUFSIZ using namespace std; int main() { // Define buffer size (BUFSIZE default is 8192 bytes) const size_t BUFFER_SIZE = 4096; char buf[BUFFER_SIZE]; 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, BUFFER_SIZE)) > 0) { write(dest, buf, size); } close(source); close(dest); return 0; }
このアプローチは、C I/O ストリーム バッファを利用します。これは簡潔で簡単で、rdbuf() メソッドを利用してファイル全体をコピーし、C ランタイムに低レベル I/O を処理させます。
// KISS-C++-Streambuffer-WAY #include <iostream> // cout, cin #include <fstream> // ifstream, ofstream using namespace std; int main() { ifstream source("from.ogv", ios::binary); ofstream dest("to.ogv", ios::binary); dest << source.rdbuf(); source.close(); dest.close(); return 0; }
C copy() アルゴリズムは、あるファイルから別のファイルにデータを効率的にコピーできます。このアプローチは、STL の堅牢なイテレータの恩恵を受け、バッファ管理を手動で処理する必要がなくなります。
// COPY-ALGORITHM-C++-WAY #include <iostream> // cout, cin #include <fstream> // ifstream, ofstream #include <ctime> // clock_t, clock() #include <algorithm> // copy #include <iterator> // istreambuf_iterator, ostreambuf_iterator using namespace std; int main() { 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(); return 0; }
このアプローチは、独自のバッファを割り当てます。メモリ管理とバッファ サイズをきめ細かく制御できます。リークを回避するには、メモリの割り当てを慎重に解除する必要があります。
// OWN-BUFFER-C++-WAY #include <iostream> // cout, cin #include <fstream> // ifstream, ofstream #include <ctime> // clock_t, clock() using namespace std; int main() { ifstream source("from.ogv", ios::binary); ofstream dest("to.ogv", ios::binary); // Determine file size and allocate buffer source.seekg(0, ios::end); ifstream::pos_type size = source.tellg(); source.seekg(0, ios::beg); char* buffer = new char[size]; // Copy file source.read(buffer, size); dest.write(buffer, size); // Cleanup delete[] buffer; source.close(); dest.close(); return 0; }
Linux 固有の sendfile() 関数は、カーネル レベルの最適化と直接データ転送を利用します。ファイル記述子の間。このアプローチは、特に大きなファイル転送の効率が高いことで知られています。
// LINUX-WAY #include <iostream> // cout, cin #include <sys/sendfile.h> // sendfile #include <fcntl.h> // open #include <unistd.h> // close #include <sys/stat.h> // stat #include <sys/types.h> // stat #include <ctime> // clock_t, clock() using namespace std; int main() { int source = open("from.ogv", O_RDONLY, 0); int dest = open("to.ogv", O_WRONLY | O_CREAT | O_TRUNC, 0644); // Determine file size struct stat stat_source; fstat(source, &stat_source); // Copy file sendfile(dest, source, 0, stat_source.st_size); close(source); close(dest); return 0; }
提供されるアプローチは、複雑さ、効率、制御の点で異なります。これらの長所と限界の概要は次のとおりです:
Approach | Pros | Cons |
---|---|---|
ANSI C | Low-level control, portable | Verbose, buffer management required |
POSIX | More control than ANSI C, handles large files | Still requires explicit buffer management |
KISS-C -Streambuffer | Concise, stream buffer manages I/O | High-level, less control over buffering |
COPY-ALGORITHM-C | Efficient, STL iterators handle data transfer | Requires caution with large files to avoid buffering issues |
OWN-BUFFER-C | Fine-grained control over buffer management | Memory management must be handled carefully to avoid leaks |
LINUX-sendfile() | Fast, kernel-level optimization | Linux-specific, requires elevated privileges |
最適なアプローチの選択は、アプリケーションの特定の要件によって異なります。小さなファイルの場合は、ifstream/ofstream の単純さで十分な場合があります。大きなファイルや効率が重要なシナリオの場合、sendfile() は優れたオプションです。最終的には、ユースケースに最適なソリューションを決定するために、さまざまなアプローチをテストしてベンチマークすることをお勧めします。
以上がC でファイルを安全かつ迅速にコピーするための最良の方法は何ですか?また、それぞれの長所と短所は何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。