我有一个以.log
格式存储的文件列表:
c:\foto\foto2003\shadow.gif
D:\etc\mom.jpg
我想从这些文件中提取名称和扩展名。你能给出一个简单方法的例子吗?
答案 0 :(得分:151)
要提取没有扩展名的文件名,请使用boost :: filesystem :: path :: stem 而不是丑陋的std :: string :: find_last_of(“。”)
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
答案 1 :(得分:19)
如果您想要一种安全的方式(即在平台之间移植而不在路径上进行假设),我建议您使用boost::filesystem
。
看起来有点像这样:
boost::filesystem::path my_path( filename );
然后,您可以从此路径中提取各种数据。 Here's the documentation of path object.
顺便说一句:还要记住,为了使用像
这样的路径c:\foto\foto2003\shadow.gif
你需要转义字符串文字中的\
:
const char* filename = "c:\\foto\\foto2003\\shadow.gif";
或者改为使用/
:
const char* filename = "c:/foto/foto2003/shadow.gif";
这仅适用于在""
引号中指定文字字符串,从文件加载路径时问题不存在。
答案 2 :(得分:14)
您必须从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 = "";
}
}
答案 3 :(得分:12)
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"
如果您需要,可以std::filesystem::path
将std::string
转换为p.filename().string()
,例如:
filename and extension: file.ext
答案 4 :(得分:3)
不是代码,但这是一个想法:
std::string
)中读取std::ifstream
,每个实例读取都将是完整路径find_last_of
\
find_last_of
执行.
,并且任何一方的子字符串都会为您提供名称+扩展名。答案 5 :(得分:0)
我还使用此片段来确定适当的斜杠字符:
boost::filesystem::path slash("/");
boost::filesystem::path::string_type preferredSlash = slash.make_preferred().native();
然后用操作系统的首选斜杠替换斜杠。如果在Linux / Windows之间不断部署,则非常有用。
答案 6 :(得分:0)
对于linux或unix机器,os有两个处理路径和文件名的函数。使用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不是好风格。我可以把它放入try / catch中 阻止两个电话之间发生的事情。
答案 7 :(得分:0)
尼古拉·默金(Nickolay Merkin)和钟雨辰(Yuchen Zhong)的回答很不错,但是从评论中您可以看到它并不完全准确。
打印时隐式转换为std :: string会将文件名括在引号中。评论也不正确。
path::filename()
和path::stem()
返回新的路径对象,而path::string()
返回对字符串的引用。因此,std::cout << file_path.filename().string() << "\n"
之类的东西可能会导致悬挂参考的问题,因为参考指向的字符串可能已被破坏。
答案 8 :(得分:0)
尝试以下技巧,从c ++中没有扩展名的路径中提取文件名,而c ++中没有外部库:
#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";
}