質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

3回答

13587閲覧

C++ ファイルコピーの方法

tuyudaku

総合スコア75

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

1グッド

0クリップ

投稿2018/11/01 08:12

編集2018/11/01 08:23

C++にて、ファイルコピーを行なう関数を作ろうと思ったのですが
いくつかの方法がありどの方法でやるかを迷っています

皆さんならどの方法で実装するかを教えてください
それぞれの長所などがいまいち分からず選びきれていない状況です
よろしくお願いします

サイトに載っていたコードを参考にしています

C++

1//system関数を利用した方法 2system( "cp test.txt /tmp" ); 3

C++

1void CopyFile( const char *from_file_name, const char *to_file_name ) 2{ 3 //streambuf_iteratorとcopy()を利用した方法 4 5 ifstream is( from_file_name, ios::in | ios::binary ); 6 ofstream os( to_file_name, ios::out | ios::binary ); 7 8 // ファイルコピー 9 istreambuf_iterator<char> iit(is); 10 istreambuf_iterator<char> end; 11 ostreambuf_iterator<char> oit(os); 12 copy( iit, end, oit ); 13}

c++

1void CopyFile( const char *from_file_name, const char *to_file_name ) 2{ 3 //fstream::rdbuf()と<<を使った方法 4 ifstream is( from_file_name, ios::in | ios::binary ); 5 ofstream os( to_file_name, ios::out | ios::binary ); 6 7 // ファイルコピー 8 os << is.rdbuf(); 9}

c++

1void my_copy(char *from[], char *to[]) { 2 //C言語標準ライブラリを利用した方法 3 FILE *f1, *f2; 4 int c; 5 6 f1 = fopen(from, "r"); 7 if (!f1) err(from); 8 9 file_exist(to); 10 f2 = fopen(to, "w"); 11 if (!f2) err(to); 12 13 while ((c = fgetc(f1)) != EOF) { 14 if (fputc(c, f2) == EOF) err(to); 15 } 16 17 fclose(f2); 18 fclose(f1); 19}

こんな方法があるよ
こっちの方が安全だよ、という情報がありましたら
よろしくお願いします

---追記
C++17は私の環境では使用できないのでstd::filesystem::copyの方法は無しでお願いします

yohhoy👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

こんにちは。

ファイルをコピーするだけなら、system関数か、std::copyですね。
Cライブラリは使わないで済むなら避けたいですし、ファイルを一度全部読むのはファイルが小さいことが判っている時だけですね。

ただ、多くの場合、ファイルの列挙やフォルダ生成等も一緒に必要になるので、C++17が使えないなら、boost::filesystemを使うだろうと思います。もし、既にQt等を使っているならそれらのライブラリを使います。

投稿2018/11/01 13:15

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tuyudaku

2018/11/02 00:20

>Cライブラリは使わないで済むなら避けたいですし やはりそうなんですね C++を使っているならなるべくCライブラリを避けて作ろうと思っていたのですが そう考えるとsystem関数のようなシステムコールなどはどうなるのだろうと思って質問しました >ファイルを一度全部読むのはファイルが小さいことが判っている時だけですね 1M程が想定され、可変であるので やはりあまり現実的ではないですね >もし、既にQt等を使っているならそれらのライブラリを使います。 その手もありましたね、まさにQtを使っています。 ただ、画面系以外の部分ではQtライブラリを使わないみたいな 暗黙の了解的なのが出来ているのでそこは要相談といった感じですw 回答ありがとうございました
guest

0

ベストアンサー

system関数が使えるのならば、それでいいと思います。

問題は移植性を考慮して使えない場合です。
ここで出てる他の3つの方法(std::copy, rdbuf, C)には問題があります。

  1. std::copy

バイト単位の読み込み・書き込みになるので容量に比例して遅くなります。
2. rdbuf
超大容量なファイルをコピーする際に問題が生じる可能性があります。
3. C
1と同じでバイト単位で読み込み・書き込みをしているので遅くなります。
さらに、"b"オプションをつけずにファイルを開いているのでWindows環境において問題が生じます。

なので適当に修正して

c++

1#include<cstdio> 2void my_copy(char * const from[], char * const to[]) { 3 constexpr std::size_t BUFSIZE = 4096; // とりあえず4KB 4 auto src = fopen(from, "rb"); 5 if (!src) err(from); 6 7 auto dst = fopen(to, "wb"); 8 if (!dst) err(to); 9 10 for(char buf[BUFSIZE]; auto size = fread(buf, 1, BUFSIZE, src);){ 11 fwrite(buf, 1, size, dst); 12 } 13 fclose(dst); 14 fclose(src); 15}

まぁ、非windows環境でsystem、windows環境でCopyFileが楽でいいと思いますけどね

投稿2018/11/01 18:21

asm

総合スコア15147

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tuyudaku

2018/11/02 00:11

>system関数が使えるのならば、それでいいと思います。 なるほど、Linuxでの使用しか考えていないのなら system関数がベターな方法なんですね バイト単位でのコピー方法の利点は どこで、なんのエラーが起きているのかが拾いやすいということでしょうかね? 回答ありがとうございました
asm

2018/11/02 00:21 編集

ファイルが途中で書き換えられたら?削除された場合は? win環境ではファイルの作成日時をコピーする? なんていう細々したものを OSの仕様に準じる と一言で済ませられるのがsystem/CopyFile最大の利点です。 --- バイト単位の利点については途中で書き換えられた場合に追随できる点ですが そもそも、そんな事されたらマトモなファイルになるかは微妙なので 個人的には使いたくないなぁと思います。 ファイルサイズを取ってきてファイルサイズの10%or10MB程度の小さい方 をバッファサイズとして使うコピーが個人的には理想です。
guest

0

C++17 を想定できるのであれば std::filesystem::copy を使うというのもひとつの方法です。

投稿2018/11/01 08:20

SaitoAtsushi

総合スコア5444

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tuyudaku

2018/11/01 08:22

あぁ...ごめんなさい... 書かなきゃと思っていたことを書くの忘れていました... C++17は私の環境では使えないのでそれは除外してください... C++17さえ使えれば... 回答ありがとうございました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問