C++ 如何从C+;中的路径提取文件名和扩展名+;
我有一个文件列表存储在C++ 如何从C+;中的路径提取文件名和扩展名+;,c++,string,file-io,C++,String,File Io,我有一个文件列表存储在.log中,语法如下: c:\foto\foto2003\shadow.gif D:\etc\mom.jpg 我想从这个文件中提取名称和扩展名。你能举一个简单方法的例子吗?不是代码,而是想法: 从输入流(std::ifstream)读取std::string),读取的每个实例都将是完整路径 在\ 从这个位置提取一个子字符串到最后,这将为您提供文件名 对执行查找中的最后一个,两边的子字符串将为您提供名称+扩展名 如果您想要一种安全的方式(即在平台之间可移植,并且不将假设放在
.log
中,语法如下:
c:\foto\foto2003\shadow.gif
D:\etc\mom.jpg
我想从这个文件中提取名称和扩展名。你能举一个简单方法的例子吗?不是代码,而是想法:
std::ifstream
)读取std::string
),读取的每个实例都将是完整路径\
执行查找
中的最后一个,两边的子字符串将为您提供名称+扩展名boost::filesystem
它看起来像这样:
boost::filesystem::path my_path( filename );
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:\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
方法查找最后一个分隔符
大概是这样的:
boost::filesystem::path my_path( filename );
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 = "";
}
}
要提取不带扩展名的文件名,请使用boost::filesystem::path::stem而不是难看的std::string::find_last_of(“.”)
boost::filesystem::path p(“c:/dir/dir/file.ext”);
std::cout我还使用此代码段确定适当的斜杠字符:
boost::filesystem::path slash("/");
boost::filesystem::path::string_type preferredSlash = slash.make_preferred().native();
然后用操作系统的首选斜杠替换斜杠。如果您经常在Linux/Windows之间部署,这将非常有用。对于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"
如果需要,您可以通过p.filename().string()
将std::filesystem::path
转换为std::string
,例如:
filename and extension: file.ext
对于linux或unix机器,操作系统有两个处理路径和文件名的函数。使用man 3 basename可以获得有关这些函数的更多信息。
使用系统提供的功能的优点是,您不必安装boost或编写自己的功能
#include <libgen.h>
char *dirname(char *path);
char *basename(char *path);
由于BaseNeMe()函数的非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不是很好的样式。我本来可以试试看的
阻止,以防两次呼叫之间发生问题 Nickolay Merkin和Yuchen Zhong的回答很好,但从评论中你可以看出,这并不完全准确
打印时隐式转换为std::string将文件名包装在引号中。这些评论也不准确
path::filename()
和path::stem()
返回一个新的路径对象和path::string()
返回对字符串的引用。因此,如 STD::CUT尝试以下技巧,从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";
}
#包括
#包括
使用std::string;
字符串getFileName(常量字符串&s){
char sep='/';
#ifdef_WIN32
sep=“\\”;
#恩迪夫
尺寸=s.rfind(sep,s.length());
if(i!=string::npos)
{
字符串文件名=s.substr(i+1,s.length()-i);
size\u t lastindex=filename.find\u last\u of(“.”);
字符串rawname=filename.substr(0,lastindex);
报税表(姓名);
}
返回(“”);
}
int main(int argc,字符**argv){
字符串路径=“/home/aymen/hello_world.cpp”;
字符串ss=getFileName(路径);
std::cout和-1表示不可移植:)为什么投票反对?如果我说的有什么问题,请告诉我,我会解决!@Kos,这太苛刻了!它符合OP的要求,文件基于windows,没有可移植性要求!至少,一个有效的windows路径可以将目录用/
分隔为嗯。我甚至不知道在路径规范中是否存在更多的警告,所以我的想法很简单——如果有一个好的库可以满足我的需要,我应该使用它,因为它可能会比我更好地实现我的目标。;@Nim,但不是有一个boost::昆虫::disperser
通用模板吗?:)+1肯定没有主站点上的示例提供了一种搜索目录的方法:使用path.extension()方法搜索日志(请参阅)事实上,这是大多数情况下的方法,但是它涉及到在某些情况下添加对外部库的不期望的依赖。如果您只想处理C++标准所提供的内容,我建议查看C++正则表达式,在这里您可以定义正则表达式来完成您想要的(在因特网上有很多例子)。。优点-由于一些额外的依赖项而没有开销。但是,这也留下了一个问题-是否需要多平台?Boost会处理路径样式,无论您使用的是Windows还是Linux。使用正则表达式,您必须自己完成。不想成为聪明的傻瓜,但它应该是path.substr而不是path.substring,对吗?同意。最简洁地回答了这个问题。事实上,p.filename()的类型是path,隐式转换时会被引号包围,因此您将得到:filename和扩展名:“file.ext”您可能需要p.filename().string()相反,在C++14/C++17中,你可以使用std::experimental::filesystem
respstd::filesystem
。请参阅下面钟宇晨的帖子。询问者想要一个简单的方法。仅为这个功能向项目添加boost不是一个简单的方法。std::filesystem是一个简单的方法。包括C++17
#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";
}