この構文の.log
に保存されているファイルのリストがあります。
c:\foto\foto2003\shadow.gif
D:\etc\mom.jpg
このファイルから名前と拡張子を抽出したい。これを行う簡単な方法の例を挙げていただけますか?
拡張子なしでファイル名を抽出するには、boostいstd :: string :: find_last_of( "。")の代わりにboost :: filesystem :: path :: stemを使用します
boost::filesystem::path p("c:/dir/dir/file.ext");
std::cout << "filename and extension : " << p.filename() << std::endl; // file.ext
std::cout << "filename only : " << p.stem() << std::endl; // file
安全な方法が必要な場合(つまり、プラットフォーム間で移植可能で、パスに仮定を置かない)、boost::filesystem
を使用することをお勧めします。
次のようになります。
boost::filesystem::path my_path( filename );
その後、このパスからさまざまなデータを抽出できます。 パスオブジェクトのドキュメントを次に示します。
ところで:また、パスを使用するために
c:\foto\foto2003\shadow.gif
文字列リテラルで\
をエスケープする必要があります。
const char* filename = "c:\\foto\\foto2003\\shadow.gif";
または、代わりに/
を使用します。
const char* filename = "c:/foto/foto2003/shadow.gif";
これは、""
引用符でリテラル文字列を指定する場合にのみ適用されます。ファイルからパスをロードする場合、問題は存在しません。
std::string
のファイルからファイル名を読み取る必要があります。 std::ostream
の文字列抽出演算子を使用できます。 std::string
にファイル名を入れたら、std::string::find_last_of
メソッドを使用して最後の区切り文字を見つけることができます。
このようなもの:
std::ifstream input("file.log");
while (input)
{
std::string path;
input >> path;
size_t sep = path.find_last_of("\\/");
if (sep != std::string::npos)
path = path.substr(sep + 1, path.size() - sep - 1);
size_t dot = path.find_last_of(".");
if (dot != std::string::npos)
{
std::string name = path.substr(0, dot);
std::string ext = path.substr(dot, path.size() - dot);
}
else
{
std::string name = path;
std::string ext = "";
}
}
C++ 17の場合:
_#include <filesystem>
std::filesystem::path p("c:/dir/dir/file.ext");
std::cout << "filename and extension: " << p.filename() << std::endl; // "file.ext"
std::cout << "filename only: " << p.stem() << std::endl; // "file"
_
ファイルシステムに関するリファレンス: http://en.cppreference.com/w/cpp/filesystem
@ RoiDantoで示唆されているように、出力の書式設定では、_std::out
_が出力を引用符で囲む場合があります。例:
_filename and extension: "file.ext"
_
必要であれば、p.filename().string()
で_std::filesystem::path
_を_std::string
_に変換できます。例:
_filename and extension: file.ext
_
コードではなく、ここにアイデアがあります:
std::string
)からstd::ifstream
を読み取ります。読み取られた各インスタンスはフルパスになりますfind_last_of
の文字列に対して\
を実行しますfind_last_of
に対して.
を実行すると、いずれかの側のサブストリングに名前と拡張子が付けられます。Nickolay MerkinとYuchen Zhongの回答は素晴らしいですが、コメントからは完全に正確ではないことがわかります。
印刷時のstd :: stringへの暗黙的な変換は、ファイル名を引用符で囲みます。コメントも正確ではありません。
path::filename()
およびpath::stem()
は新しいパスオブジェクトを返し、path::string()
は文字列への参照を返します。したがって、std::cout << file_path.filename().string() << "\n"
のようなものは、参照が指す文字列が破壊された可能性があるため、参照のダングリングで問題を引き起こす可能性があります。
LinuxまたはUNIXマシンの場合、osにはパスとファイル名を扱う2つの関数があります。これらの関数に関する詳細情報を取得するには、man 3 basenameを使用してください。システムが提供する機能を使用する利点は、boostをインストールしたり、独自の機能を作成したりする必要がないことです。
#include <libgen.h>
char *dirname(char *path);
char *basename(char *path);
マニュアルページのサンプルコード:
char *dirc, *basec, *bname, *dname;
char *path = "/etc/passwd";
dirc = strdup(path);
basec = strdup(path);
dname = dirname(dirc);
bname = basename(basec);
printf("dirname=%s, basename=%s\n", dname, bname);
Basename()関数のconst以外の引数タイプのため、C++コード内でこれを使用すると、少し非直線的です。コードベースの簡単な例を次に示します。
string getFileStem(const string& filePath) const {
char* buff = new char[filePath.size()+1];
strcpy(buff, filePath.c_str());
string tmp = string(basename(buff));
string::size_type i = tmp.rfind('.');
if (i != string::npos) {
tmp = tmp.substr(0,i);
}
delete[] buff;
return tmp;
}
New/deleteの使用は良いスタイルではありません。 2つの呼び出しの間に何かが起こった場合に備えて、try/catchブロックに入れることもできます。
また、このスニペットを使用して適切なスラッシュ文字を決定します。
boost::filesystem::path slash("/");
boost::filesystem::path::string_type preferredSlash = slash.make_preferred().native();
そして、スラッシュをOSの優先スラッシュに置き換えます。 Linux/Windows間で絶えず展開している場合に役立ちます。