C++でファイルを削除する場合、主に二つの方法があります。
ひとつは従来からある標準Cライブラリの std::remove を使う方法、もうひとつはC++17以降で利用可能な <filesystem> の remove を使う方法です。
それぞれの特徴や注意点を理解することで、より安全で確実なファイル操作が可能になります。
ファイル削除は不可逆の操作であり、一度削除すると元に戻せないため、プログラム設計においてはエラーハンドリングや存在確認の方法も慎重に考える必要があります。
std::remove を使ったファイル削除
std::remove は <cstdio> に定義されており、指定したファイルを削除する最もシンプルな方法です。
この関数は削除に成功した場合は 0 を返し、失敗した場合は 0 以外を返します。
失敗の原因としては、削除対象のファイルが存在しない場合や、ファイルが読み取り専用である場合、またはアクセス権限が不足している場合などが考えられます。
失敗した理由を確認する場合は perror を使うことで簡単にエラー内容を出力できます。
ここで注意すべきは、C++には同じ名前の std::remove が <algorithm> にも存在することです
<algorithm> の std::remove はコンテナから要素を削除するためのアルゴリズムであり、ファイル削除とは全く別の用途です。
C++でファイルを削除したい場合は必ず <cstdio> の std::remove を使用する必要があります。
従来の std::remove はシンプルで動作も軽量ですが、エラー処理や例外処理に関してはあまり柔軟性がなく、存在確認や権限不足の扱いがやや限定的であるため、より安全な方法が求められる場合があります。
std::filesystem::remove を使ったモダンな方法
C++17以降では、<filesystem> の remove を使うことで、より安全で柔軟なファイル削除が可能になります。
std::filesystem::remove は削除対象のファイルが存在し、かつ削除に成功した場合に true を返します。
対象が存在しない場合は false を返し、削除処理で何らかのエラーが発生した場合は例外を投げます。
また、例外を使わないオーバーロードを利用すれば、エラーコードで状態を確認することもできます。
この方法の利点として、空のディレクトリも削除可能であることが挙げられます。
従来の std::remove ではファイルしか削除できませんでしたが、std::filesystem::remove は空ディレクトリを対象にすることができます。
ただし、ディレクトリ内にファイルやサブディレクトリが存在する場合は削除できないため、中身ごと削除する場合は remove_all を使用します。
remove_all は便利ですが非常に強力で、誤ったパスを指定すると意図しないファイルやディレクトリまで削除してしまうリスクがあります。
特にユーザー入力をそのまま渡す場合は、削除対象が本当に安全な場所であるか十分に確認する必要があります。
ファイル削除に関する注意点
存在確認の落とし穴
プログラムの中で「ファイルが存在するか確認してから削除する」という方法は一見安全に思えます。
しかし、確認後に他のプロセスによってファイルが削除されたり置き換えられたりする場合があります。
このため、存在確認に依存せず、削除処理自体の戻り値やエラーコードで状態を確認する方が安全です。
使用中ファイルの扱い
ファイルが他のプロセスで使用中の場合、削除が成功するかどうかはOSによって異なります
。Windowsでは、別プロセスがそのファイルを開いている場合、削除に失敗することが多いです。
一方、LinuxやmacOSなどのUnix系OSでは、ファイルが使用中でもディレクトリエントリから削除できる場合があります。
この場合、開いているプロセスは引き続きファイルにアクセスでき、プロセスが閉じたときに初めて実体が解放されます。
シンボリックリンクの取り扱い
シンボリックリンクを削除する場合、std::filesystem::remove はリンクそのものを削除し、リンク先は残ります。
リンク先のファイルを誤って削除しないように注意が必要です。
remove_all を使う場合も、リンクやジャンクション、マウントポイントに対して意図せず再帰削除してしまうリスクがあります。
一括削除のリスク
ディレクトリ内の特定条件に合うファイルを一括で削除する場合、ディレクトリの存在確認やファイル種別の確認、エラー処理をきちんと行うことが重要です。
特に再帰的に削除する場合は、対象のディレクトリやパスを慎重に確認し、想定外のファイルやディレクトリを削除しないようにする必要があります。
まとめ
- 単純なファイル削除には
std::removeが利用可能ですが、より安全でモダンな方法としては C++17 以降の<filesystem>のremoveを使うことが推奨されます。 - 空のディレクトリは
std::filesystem::removeでも削除可能ですが、ディレクトリ内にファイルやサブディレクトリがある場合はremove_allを使用する必要があります。 - ファイル削除の際は、使用中のファイル、権限不足、存在確認のタイミング、シンボリックリンクや一括削除のリスクなどに十分注意することが重要です。
- 削除操作は不可逆であるため、必要に応じてバックアップやエラーハンドリングを適切に組み込むことが安全です。
C++17以降を使う場合は、エラーコードや戻り値を確認しながら <filesystem> の機能を活用することで、安全かつ柔軟なファイル削除処理を実装できます。
以上、C++でファイル削除する方法についてでした。
最後までお読みいただき、ありがとうございました。
