目次
はじめに
C++でファイル操作を行う際、ファイルのダウンロード進捗を表示したり、読み込みに必要なメモリ量を判断したりするために、ファイルのサイズを知りたい場面があります。
C++17で導入された <filesystem>
ライブラリは、このファイルサイズを取得するための**std::filesystem::file_size()
**という、シンプルで移植性の高い関数を提供しています。
【前提】C++17とは?
C++17は、2017年に正式化されたC++言語の規格です。<filesystem>
ライブラリはこのC++17で導入されたため、利用するにはC++17に対応したコンパイラと、適切なコンパイラ設定(および、一部の環境ではリンカ設定)が必要になります。
file_size()
を使ったサンプルコード
このコードは、まずテスト用のテキストファイルを作成して12バイトのデータを書き込み、そのファイルに対して file_size()
を呼び出して、サイズが正しく 12
と返されることを確認します。
完成コード
#include <iostream>
#include <filesystem>
#include <fstream> // ofstream
#include <cstdint> // uintmax_t
// filesystem名前空間のエイリアス
namespace fs = std::filesystem;
int main() {
fs::path test_filepath = "sample.txt";
// 1. 12バイトのテストファイルを作成
std::ofstream test_file(test_filepath);
test_file << "Hello, C++!"; // 11文字 + NULL文字で12バイトではないが、ここでは11バイト
test_file.close();
// 修正:ofstreamはNULL文字を書き込まないので、11バイトのファイルができます。
// 分かりやすさのため、内容をABCDEFGHIJK (11文字) にします。
// 再度修正: "Hello, C++!" は11文字です。ファイルサイズは11バイトになります。
// "ABCDEFGHIJK"も11文字です。
// 当初のユーザーコード "0123456789" は10文字なので10バイトです。
// ここでは分かりやすく "123456789012" (12バイト) を書き込みます。
std::ofstream ofs(test_filepath);
ofs << "123456789012";
ofs.close();
try {
// 2. file_size()でファイルサイズを取得
uintmax_t size_in_bytes = fs::file_size(test_filepath);
std::cout << "ファイル「" << test_filepath << "」のサイズは "
<< size_in_bytes << " バイトです。" << std::endl;
} catch (const fs::filesystem_error& e) {
std::cerr << "エラーが発生しました: " << e.what() << std::endl;
}
// 3. テストファイルを削除
fs::remove(test_filepath);
return 0;
}
実行結果の修正: 上記のコードでは12バイトのファイルを生成するので、結果は12
になります。
ファイル「"sample.txt"」のサイズは 12 バイトです。
コードの解説
fs::file_size(path)
- 機能: 引数で渡されたパス
path
が指すファイルのサイズを、バイト単位で返します。 - 戻り値の型:
uintmax_t
という、非常に大きな値を扱える符号なし整数型です。 - エラー処理:
- 指定したパスが存在しない場合や、ファイルではなくディレクトリを指している場合、
std::filesystem::filesystem_error
例外をスローします。 - そのため、
try-catch
ブロックで囲んでおくと、プログラムがクラッシュするのを防ぐことができ、より安全です。
- 指定したパスが存在しない場合や、ファイルではなくディレクトリを指している場合、
まとめ
今回は、C++17の <filesystem>
ライブラリを使って、ファイルのサイズを安全に取得する file_size()
関数について解説しました。
<filesystem>
ヘッダーをインクルードする。fs::file_size(パス)
の形で呼び出す。- 戻り値はバイト単位のファイルサイズ。
- パスが存在しない場合などに例外を投げるため、
try-catch
でのエラーハンドリングが推奨される。
ファイルを開く前にサイズを確認したり、ファイルの正当性をチェックしたりする際に、この関数は非常に便利です。