我正在编写一个需要检查和操作Windows路径的跨平台应用程序.
具体来说,对于我现在遇到的特殊问题,我需要知道路径是绝对的还是相对的.
当前代码使用boost::filesystem::path的当然类似于Windows上的魅力:
boost::filesystem::path the_path(the_path_as_a_string);
if (!the_path.has_root_path()) { /* do stuff */ }
Run Code Online (Sandbox Code Playgroud)
这种方法的问题在于boost::filesystem::path只有两种模式:原生模式和便携模式.这意味着当我在Linux下编译时,Windows路径语法不可用(它#ifdef在源代码中被删除).因此,路径"C:\ path"在Windows中被认为是绝对的,但在Linux中则相对.
你们能推荐一个可以检查和操作Windows路径的跨平台C++库吗?
现在,我要做的唯一Windows路径操作是检查路径是否是绝对路径.
我将用于绝对路径的标准是它包含一个驱动器号,并且路径以\.该标准下的绝对路径的示例是C:\path.这些都是这个标准下相对路径的例子:C:path,\path.
所以我尝试移植我的旧项目(从boost 1.44到1.61)我发现path.native_file_string()没有boost::filesystem v3...
那么模拟有什么用path.native_file_string()呢boost::filesystem v3?(我不想再使用v2,但我需要诸如native_file_string之类的功能)
我想检查字符串是否name指的是我可以打开和读取的文件,因此它可以是常规文件或符号链接。
我第一次使用这个:
std::ifstream in(name.c_str());
if (!in.is_open()) {
// throw exception!
}
Run Code Online (Sandbox Code Playgroud)
但是在name引用目录名称时它没有抛出异常。
现在我正在使用这个:
if (!fs::exists(name) || fs::is_directory(name)) {
// throw exception!
}
Run Code Online (Sandbox Code Playgroud)
但如果它是一个目录的符号链接,它(大概)不会抛出。这也是同样的道理:
if (!fs::is_regular_file(name) && !fs::is_symlink(name)) {
// throw exception!
}
Run Code Online (Sandbox Code Playgroud)
有没有更好的办法?
我想使用 boost::filesystem 从文件中获取所有者和组,但从未找到任何方法来做到这一点。
我可以获得文件的权限,但由于我不知道文件的所有者,这没有任何意义。
我找到了 posix fstat 函数,但我再次想使用 boost 或另一个 C++ 库而不是 C 函数。
特别是,我希望能够访问文件的user_id和group_id。我可以找到与stat结构最接近的等效项是file_status类,但这似乎没有适当的字段。
任何的想法?干杯,本。
谁能告诉我如何使boost::filesystem::path不区分大小写?通常,区分大小写是本机平台决定,但是对于我的应用程序来说这并不是那么简单,因为路径详细信息是从二进制文件中提取的,并且应用程序要求是无论我在什么平台上运行,我都必须处理所有路径都不区分大小写。
迄今为止,我一直这样做的方法是使用boost::filesystem::path::generic_string()方法将我正在比较的路径放入通用字符串格式中以进行字典比较。接下来,我将字符串转换为小写并使用 std::string 函数来执行比较和其他运算符方法。显然,这是次优的,因为我希望能够对路径而不是字符串执行字典比较。在内部,boost 的路径运算符 <()实现使用路径迭代器进行巧妙的字典式路径比较 - 这与字符串字典式比较不同。
我认为有某种方法提供特殊的用户定义字符串类型作为构造函数中增强路径的内部表示,但我不确定如何做到这一点。通常,这种性质的大小写不敏感将通过关联的特征类来执行 - 正如您在下面用于 UtlCIString(实用程序不区分大小写的字符串)的不区分大小写的字符串特征字符类中所看到的。如果可以将不同的字符串类型关联为内部字符串类,我将使用以下内容,但我不确定如何:
// case insensitive character traits
// inherited copy (preserves case),
// case insensitive comparison, search
struct traits_nocase : std::char_traits<char>
{
static bool eq(const char& c1, const char& c2) {
return toupper(c1) == toupper(c2);
}
static bool lt(const char& c1, const char& c2) {
return toupper(c1) < toupper(c2);
}
static int compare(const char* s1, const char* s2, …Run Code Online (Sandbox Code Playgroud) 我在 Windows 上,并且正在std::filesystem::path从std::string. 根据构造函数参考(强调我的):
如果源字符类型为
char,则假定源的编码是本机窄编码(因此在 POSIX 系统上不会发生转换)
如果我理解正确的话,这意味着字符串内容将在 Windows 下被视为以 ANSI 编码。要将其视为以 UTF-8 编码,我需要使用std::filesystem::u8path()function. 请参阅演示:http://rextester.com/PXRH65151
我希望 的构造函数path将窄字符串的内容视为 UTF-8 编码。因为boost::filesystem::path我可以使用imbue()方法来做到这一点:
boost::filesystem::path::imbue(std::locale(std::locale(), new std::codecvt_utf8_utf16<wchar_t>()));
Run Code Online (Sandbox Code Playgroud)
但是,我在 中没有看到这样的方法std::filesystem::path。有没有办法实现这种行为std::filesystem::path?还是我需要u8path随地吐痰?
当参数是目录时,为什么此代码会引发错误?
使用boost::recursive_directory_iterator和使用std::cout语句,我可以看到它从不打印目录;只有文件。但是,当我尝试调用 时boost::filesystem::file_size(),会抛出一个错误,基本上是说我正在尝试获取目录的文件大小。
错误(参数为"/home"):
terminate called after throwing an instance of 'boost::filesystem::filesystem_error'
what(): boost::filesystem::file_size: Operation not permitted: "/home/lost+found"
Aborted
Run Code Online (Sandbox Code Playgroud)
#include <iostream>
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;
int main(int argc, char* argv[])
{
if (argc != 2) return -1;
const fs::path file{argv[1]};
if (!fs::exists(file)) return -1;
if (fs::is_regular_file(file))
std::cout << file << " [ " << fs::file_size(file) << " ]\n";
else if (fs::is_directory(file))
for (const fs::directory_entry& f : fs::recursive_directory_iterator{file})
std::cout << f.path().filename() …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用 Meson 构建系统构建一段使用新的 C++17 文件系统库的 C++ 代码。
这是meson.build涉及的文件:
if not compiler.has_header('filesystem') # This is OK
warning('The compiler has no <filesystem> header file')
endif
filesystem_dep = dependency('libc++fs', modules : ['filesystem'])
test_exe = executable('test', test_src,
include_directories : include_dirs,
dependencies : filesystem_dep
)
Run Code Online (Sandbox Code Playgroud)
如果使用 boost::filesystem 库,这应该是正确的语法:
filesystem_dep = dependency('boost', modules : ['filesystem'])
Run Code Online (Sandbox Code Playgroud)
如何指定我想要标准 C++ 库中包含的版本?这是我尝试过但没有成功的方法:'libc++fs'、'stdlib'、'stdc++'、'libc++'、'c++'、'c++17'。
这是我从 Meson 收到的错误消息:
src/meson.build:33:0: 错误: 未找到本机依赖项“libc++fs”
我目前使用的编译器是LLVM/clang。
给出以下代码:
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
int main()
{
fs::path fsBase = "/base";
fs::path fsAppend = "/append";
auto fsResult = fsBase / fsAppend;
std::cout << "fsResult: " << fsResult << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
通常,预期的结果是/base/append,但它实际上给出了/append。
fs::path::append的描述确实表明了这种行为:
如果 p.is_absolute() || (p.has_root_name() && p.root_name() != root_name()),然后用 p 替换当前路径,就像用 operator=(p) 并完成一样。
然而,行为std::experimental::filesystem和boost::filesystem不同的是,这给了预期/base/append。请参阅示例。
问题是为什么它会这样?为什么用append()函数替换路径?
boost-filesystem ×10
c++ ×9
boost ×6
c++17 ×2
filepath ×2
path ×2
clang ×1
file ×1
filesystems ×1
fstat ×1
meson-build ×1
stat ×1
stl ×1
utf-8 ×1