C++1zでは、ファイルパス、ディレクトリ、ファイルのコピー・移動などを扱うファイルシステムライブラリが導入されます。
このライブラリは、Boost Filesystem Library v3をベースにしています。basic_path<CharT>
のように文字型をパラメータとするのではなく、path
クラスが用意され、内部で文字エンコーディングが行われます。
C++1zのファイルシステムライブラリが議論されていくにつれてBoost.Filesystemも追従して更新されていますので、Boost 1.61.0現在では、この2つの差異は小さくなっています。
ファイルシステムライブラリの機能は、<filesystem>
ヘッダのstd::filesystem
名前空間で定義されます。
#include <filesystem> namespace fs = std::filesystem; int main() { fs::path p1 = "C:/"; fs::path p2 = "a.txt"; // operator/()で2つのパスを連結する // operator+=(), concat()メンバ関数を使用してもよい fs::path p = p1 / p2; // ファイルをfromからtoにコピーする // エラーが発生した場合は、std::filesystem::filesystem_error例外が送出される fs::path from = p; fs::path to = "C:/b.txt"; fs::copy_file(from, to); }
エラー報告
ファイルシステムライブラリのエラー報告は、std::filesystem::filesystem_error
例外を送出するか、std::error_code
オブジェクトを返すかのどちらかを、ユーザーが選択できます。
ファイルコピーの場合は、以下のようになります:
#include <iostream> #include <filesystem> namespace fs = std::filesystem; int main() { fs::path from = "C:/a.txt"; fs::path to = "C:/b.txt"; // デフォルトでは、エラー発生時に例外を送出する try { fs::copy_file(from, to); } catch (fs::filesystem_error& e) { std::cout << e.what() << std::endl; throw; } // 最後の引数にerror_codeオブジェクトへの参照を渡すと、 // 例外送出の代わりにerror_codeオブジェクトにエラー情報が格納される std::error_code error; fs::copy_file(from, to, error); if (error) { std::cout << error.message() << std::endl; } }
文字エンコーディング
std::filesystem::path
クラスは、文字コード関係の機能が内部に入っており、OSネイティブの文字コードでファイルパス文字列を取得したり、自分がほしい文字コードでファイルパス文字列を取得できたりします。
native()
メンバ関数は、OSネイティブの文字コードでファイルパス文字列のstd::basic_string
を返します。文字の型は、POSIXベースのOSではchar
、Windowsではwchar_t
になります。文字コードもOSネイティブのものになります。
// Windowsの場合 path p = "a.txt"; path::string_type str = p.native(); // string_typeはstd::wstring型
// POSIXベースOSの場合 path p = "a.txt"; path::string_type str = p.native(); // string_typeはstd::string型
文字コードを指定したい場合は、以下のメンバ関数を使用します。
メンバ関数 | 文字コード |
---|---|
std::string string() const |
OSネイティブのマルチバイト文字コード |
std::wstring wstring() const |
OSネイティブのワイド文字コード |
std::string u8string() const |
UTF-8 |
std::u16string u16string() const |
UTF-16 |
std::u32string u32string() const |
UTF-32 |
Unicodeの正規化に関する規定はとくにありません。
パスの汎用フォーマット
パスのフォーマットには、たとえばWindowsの"C:\\a.txt"
ようにバックスラッシュでディレクトリを区切るものと、"C:/a.txt"
のようにスラッシュで区切るものがあり、後者をこのライブラリでは汎用パスフォーマット(generic path format)と呼んでいます。
汎用フォーマットでパス文字列を取得したい場合に、以下のメンバ関数が使用できます。
template <class EcharT, class traits = char_traits<EcharT>, class Allocator = allocator<EcharT> > basic_string<EcharT, traits, Allocator> generic_string(const Allocator& a = Allocator()) const; std::string generic_string() const; std::wstring generic_wstring() const; std::string generic_u8string() const; std::u16string generic_u16string() const; std::u32string generic_u32string() const;
文字コードは、前述したものと同様です。
Boost.Filesystemとの差異
Boost 1.61.0のBoost.Filesystemライブラリと比較して、設計として以下の差異があります。
日時を表す型が、Boost.Filesystemライブラリではstd::time_t
ですが、標準の方はstd::chrono::time_point<trivially-clock>
となっています。Clockの型は実装定義です。日時は、ファイルの最終日時を取得・設定する際に使用します。
ロケールの扱いが少し違います。Boost.Filesystemのpath
クラスはimbue()
メンバ関数を持っていますが、標準の方はありません。Boost.Filesystemのpath
クラスはコンストラクタでcodecvt
オブジェクトをとりますが、標準の方はlocale
オブジェクトをとります。 私が少し調べて気づいたのはこれくらいです。細かい機能のありなしはありますが、設計として異なるのはこれくらいでしょう。
参照
- N3239 Filesystem Library Update for TR2 (Preliminary)
- N3335 Filesystem Library for C++11/TR2 (Revision 1)
- N3365 Filesystem Library Proposal (Revision 2)
- N3399 Filesystem Library Proposal (Revision 3)
- N3505 Filesystem Library Proposal (Revision 4)
- N3693 Working Draft, Technical Specification – File System
- N3790 Working Draft, Technical Specification – File System
- N3940 Working Draft, Technical Specification – File System
- N4099 Working Draft, Technical Specification — File System
- N4100 Programming Languages — C++ — File System Technical Specification
- P0218R0 Adopt File System TS for C++17
- P0218R1 Adopt File System TS for C++17
お断り
この記事の内容は、C++1zが正式リリースされる際には変更される可能性があります。正式リリース後には、C++日本語リファレンスサイトcpprefjpの以下の階層の下に解説ページを用意する予定です。