我需要一个 POSIX 或 Linux API 函数,它接受文件路径并返回此文件的扩展名。每个平台都应该有一个,但对于 Linux,我不能。它叫什么?
4 回答
首先用于strrchr
查找'.'
路径名中的最后一个。如果它不存在,则没有“扩展”。
接下来,用于检查last 之后strchr
是否有。如果是这样,则最后一个位于目录组件中,而不是文件名中,因此没有扩展名。'/'
'.'
'.'
否则,您会找到扩展名。您可以将指向位置的指针'.'
直接用作 C 字符串。除非原始字符串在使用前被释放或破坏,否则无需将其复制到新存储中。
注意:以上假设您将“扩展”定义为仅最终'.'
分隔的组件。如果您想将.tar.gz
和之类的东西考虑.cpp.bak
为扩展,则可以使用稍微不同的方法:
首先,使用strrchr
找到最终的'/'
. 如果未找到,则将字符串的开头视为结果。
其次,使用从刚刚找到的位置开始strchr
查找第一个。'.'
结果就是你的扩展。
我认为这没有默认功能。
在我的文件系统库中,我只应用字符串操作。
首先,我从完整路径中获取带有扩展名的文件名,查找/
分隔符并提取最后一个之后的所有内容。然后,我抓取第一个.
点字符之后的所有内容,包括点本身。到目前为止效果很好。
请记住,某些系统文件可以以.
点字符开头 - 因此在提取扩展名之前检查文件名是否以点字符开头。
算法
- 通过从左侧删除文件夹名称从完整路径获取文件名:
/home/test/.myfile.cpp.bak
->/test/.myfile.cpp.bak
->/.myfile.cpp.bak
->.myfile.cpp.bak
- 检查文件名是否以
.
:- 如果是,请将其从当前文件名中删除
.myfile.cpp.bak
->myfile.cpp.bak
- 如果是,请将其从当前文件名中删除
- 现在,
.
从左侧提取第一个之后的所有内容(如果您想要多个扩展名) - 否则,提取.
左侧 最后一个之后的所有内容myfile.cpp.bak
->.cpp.bak
(第一种情况)myfile.cpp.bak
->.bak
(第二种情况)
包括文件系统的提升有点太多了。但随着 boost 实现达到 TR2 并在 Visual Studio 中实现,也许是时候开始研究它了。
http://cpprocks.com/introduction-to-tr2-filesystem-library-in-vs2012/
http://msdn.microsoft.com/en-us/library/hh874694.aspx
在我看来,解决这个问题的最佳方法(在没有 API 函数的情况下,这本身很奇怪)是将 Vittorio 和 R. 的答案与basename
采用路径并返回文件名的函数结合起来,如果路径指向一个文件: http: //linux.die.net/man/3/basename
我还将生成的字符串转换为 UTF-16mbstowcs
并使用以下命令进行所有查找std::wstring
:
std::wstring fileExtFromPath (const char * path)
{
const char * fileName = basename(filePath);
wchar_t buffer [MAX_PATH] = {0}; // Use mblen if you don't like MAX_PATH
const std::wstring fileNameW (buffer);
const size_t pointPosition = fileNameW.rfind(L".");
const std::wstring fileExtW = pointPosition == 0 ? std::wstring() : fileNameW.substr( + 1);
return fileExtW;
}