我有一个文件列表存储在一个名为.log
的文件中,格式如下:
c:\foto\foto2003\shadow.gif
D:\etc\mom.jpg
我想从这些文件中提取名称和扩展名。你能给出一个简单的示例来解决这个问题吗?
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
对于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 :: filesystem :: path
转换为std :: string
才能使用std :: cout
。 http://en.cppreference.com/w/cpp/filesystem/path/filename 但是,如果您有不同的看法,请随时发表评论或再次编辑帖子。 - Yuchenstd::cout
可以依赖于隐式转换。然而,由于 std::cout
后面的注释说 file.ext 和 file,因此必须在注释中添加 .string()
或者将它们改为 "file.ext" 和 "file"。使用 Visual C++ 确实没有区别(即使没有 string()
,输出也没有引号),但是使用 gcc 6.1 如果省略 .string()
,则输出会带有引号。请参见 http://coliru.stacked-crooked.com/view?id=a55ea60bbd36a8a3 - Roi Dantonboost::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 = "";
}
}
std::ifstream
)中读取一个std::string
,每个实例读取的将是完整路径。find_last_of
,查找\
.
的最后出现位置,并在其两侧提取子串,这将给出名称+扩展名。boost::insects::disperser<T>
的通用模板可以用来做这个吗? :) - Kos#include <iostream>
#include <string>
using std::string;
string getFileName(const string& s) {
char sep = '/';
#ifdef _WIN32
sep = '\\';
#endif
size_t i = s.rfind(sep, s.length());
if (i != string::npos)
{
string filename = s.substr(i+1, s.length() - i);
size_t lastindex = filename.find_last_of(".");
string rawname = filename.substr(0, lastindex);
return(rawname);
}
return("");
}
int main(int argc, char** argv) {
string path = "/home/aymen/hello_world.cpp";
string ss = getFileName(path);
std::cout << "The file name is \"" << ss << "\"\n";
}
std::filesystem::path
以及它的stem()
函数,这种方法已经过时了。 - Craig Reynolds我也使用这个代码片段来确定适当的斜杠字符:
boost::filesystem::path slash("/");
boost::filesystem::path::string_type preferredSlash = slash.make_preferred().native();
然后将斜杠替换为操作系统的首选斜杠。如果经常在Linux/Windows之间部署,则非常有用。
对于 Linux 或 Unix 系统,操作系统有两个处理路径和文件名的函数。使用 man 3 basename 获取有关这些函数的更多信息。 使用系统提供的功能的优点是您不必安装 Boost 或编写自己的函数。
#include <libgen.h>
char *dirname(char *path);
char *basename(char *path);
来自 man 页面的示例代码:
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);
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不是好的编程风格。我本可以将其放入try/catch块中,以防在两个调用之间发生了什么。
文件名和扩展名:"file.ext"
你可能想使用 p.filename().string() 代替。 - James Hirschornstd::experimental::filesystem
或std::filesystem
。请参见下面的Yuchen Zhong的帖子。 - Roi Danton