【C++17】std::filesystem でパスから拡張子を除いたファイル名 (stem) を取得する方法

目次

はじめに

C++でファイルパスの文字列を扱う際、「document.txt」というパスから、拡張子 .txt を除いた「document」の部分だけを抜き出したい、という場面は頻繁にあります。

従来は、文字列検索で最後の . を探し、それより前の部分文字列を取得する、といった手動での処理が必要でした。

C++17で導入された <filesystem> ライブラリは、このようなパスの構成要素を解析・操作するための、非常に強力で便利なツールセットを提供します。その中の一つ、.stem() メンバ関数を使えば、この処理を一行で、安全かつ直感的に行うことができます。


【前提】C++17とは?

C++17は、2017年に正式化されたC++言語の規格です。<filesystem> ライブラリはこのC++17で導入されたため、利用するにはC++17に対応したコンパイラと、適切なコンパイラ設定(および、一部の環境ではリンカ設定)が必要になります。


.stem() を使ったサンプルコード

このコードは、いくつかの異なる形式のパス文字列に対して .stem() を呼び出し、その挙動を確認します。

完成コード

#include <iostream>
#include <filesystem> // filesystemライブラリ
#include <string>

// filesystem名前空間のエイリアス
namespace fs = std::filesystem;

int main() {
    // 1. 通常のファイル名
    fs::path p1("report.docx");
    std::cout << p1 << " -> .stem() -> " << p1.stem() << std::endl;

    // 2. 拡張子がないファイル名
    fs::path p2("myfile");
    std::cout << p2 << " -> .stem() -> " << p2.stem() << std::endl;

    // 3. ドットが複数あるファイル名
    fs::path p3("archive.tar.gz");
    std::cout << p3 << " -> .stem() -> " << p3.stem() << std::endl;

    // 4. フルパス
    fs::path p4("/home/user/document.pdf");
    std::cout << p4 << " -> .stem() -> " << p4.stem() << std::endl;

    // 5. ディレクトリパス
    fs::path p5("/home/user/");
    std::cout << p5 << " -> .stem() -> " << p5.stem() << std::endl;

    return 0;
}

実行結果

"report.docx" -> .stem() -> "report"
"myfile" -> .stem() -> "myfile"
"archive.tar.gz" -> .stem() -> "archive.tar"
"/home/user/document.pdf" -> .stem() -> "document"
"/home/user/" -> .stem() -> ""

コードの解説

fs::path p1("report.docx");

std::filesystem::path は、ファイルシステムのパスを表現し、操作するためのクラスです。文字列から path オブジェクトを構築します。

p1.stem()

  • 機能: path オブジェクトが保持するパスのファイル名部分から、最後の拡張子とその前の . を取り除いたものを返します。
  • 戻り値: path オブジェクト。std::cout などで表示する際は、暗黙的に文字列に変換されます。
  • 挙動の詳細:
    • "report.docx": ファイル名 report.docx から最後の拡張子 .docx を除いた "report" を返します。
    • "archive.tar.gz": ファイル名 archive.tar.gz から、最後の拡張子 .gz だけを除いた "archive.tar" を返します。
    • "/home/user/document.pdf": パス全体からファイル名部分 document.pdf を認識し、その stem である "document" を返します。
    • "/home/user/": パスにファイル名部分が含まれない(ディレクトリで終わっている)ため、stem は空文字列 "" を返します。

まとめ

今回は、C++17の <filesystem> ライブラリを使って、パスから拡張子を除いたファイル名部分を取得する .stem() メソッドについて解説しました。

  • <filesystem> ヘッダーをインクルードする。
  • std::filesystem::path オブジェクトを作成する。
  • .stem() メンバ関数を呼び出す。

.stem() は、パス文字列を手動で解析する手間を省き、様々な形式のパスに対して一貫した、安全な方法でファイル名の本体を取得できる、非常に便利なツールです。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次