- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我试图得到 sf::String
进入 std::filesystem::u8path
.我的第一种方法是将其转换为 std::string
, (std::string)sfstringbar
但它认为它是一个单字节字符,我也试过 auto x = sfstringbar.toUtf8()
std::string(x.begin(), x.end())
但一样。我的第二种方法是将它作为 char
传递。数组,希望可以使用 UTF 8 编码读取它,但仍然会发生同样的情况。
编辑:
char* makeutf8str(str string) {
std::basic_string<sf::Uint8> utf8 = string.toUtf8();
std::vector<char>* out = new std::vector<char>;
for (auto x = utf8.begin(); x != utf8.end(); x++) {
out->push_back(*x);
}
return &(out->at(0));
}
bool neaxfile::isfile(str file) {
std::cout << "\nThis: " << makeutf8str(file) << "\n";
return std::filesystem::is_regular_file(std::filesystem::u8path(makeutf8str(file)));
}
这是我尝试的第二个解决方案。我有一个名为
Яyes.txt
的文件举个例子,但是当我通过检查它是否存在时,它说它不存在。因为
makeutf8str()
函数拆分
Я
进入
Ð
和
¯
.我似乎无法让编码器正常工作。
str neaxfile::getcwd() {
std::error_code ec;
str path = std::filesystem::current_path(ec).u8string();
if (ec.value() == 0) {
return path;
} else {
return '\0';
}
}
std::vector<str> neaxfile::listfiles() {
std::vector<str> res;
for (auto entry : std::filesystem::directory_iterator((std::string)neaxfile::getcwd())) {
if (neaxfile::isfile(entry.path().wstring())) res.push_back(entry.path().wstring());
}
return res;
}
我尝试了下面的第一个解决方案。它不再打印
Я
.但它仍然不能确认这是一个文件。我尝试使用该 ^ 列出文件
最佳答案
std::filesystem::u8path()
"从 p
s [或 char
s (C++20 起)] 的 UTF-8 编码序列构造路径 char8_t
, 作为 std::string
或 std::string_view
提供,或者作为一个以空字符结尾的多字节字符串,或者作为一个 [first, last) 迭代器对。"
一个 std::string
可以保存一个 UTF-8 编码的字符序列(最好在 C++20 中使用 std::u8string
)。 sf::String::ToUtf8()
返回一个 UTF-8 编码的 std::basic_string<Uint8>
.您可以简单地转换 UInt8
数据到 char
构建 std::string
,不需要你的makeutf8str()
使用函数std::vector<char>
或返回原始 char*
完全没有(尤其是因为它无论如何都会泄漏std::vector
)。
您可以使用 std::string
采用 char*
的构造函数和 size_t
作为输入,例如:
std::string makeutf8str(const str &string) {
auto utf8 = string.toUtf8();
return std::string(reinterpret_cast<const char*>(utf8.c_str()), utf8.size());
}
或者,您可以使用
std::string
将一系列迭代器作为输入的构造函数(尽管您声称,这应该可以正常工作),例如:
std::string makeutf8str(const str &string) {
auto utf8 = string.toUtf8();
return std::string(utf8.begin(), utf8.end());
}
无论哪种方式都适用于
std::cout
和
std::filesystem::u8path()
,例如:
bool neaxfile::isfile(const str &file) {
auto utf8 = makeutf8str(file);
std::cout << "\nThis: " << utf8 << "\n";
return std::filesystem::is_regular_file(std::filesystem::u8path(utf8));
}
话虽如此,Unicode 字符
Я
以 UTF-8 编码为字节
0xD0 0xAF
,当解释为 Latin-1 而不是 UTF-8 时,将显示为
Я
.这意味着
std::string
数据被正确地 UTF-8 编码,只是没有被正确处理。例如,如果您的控制台无法处理 UTF-8 输出,那么您将看到
Я
而不是
Я
.但是,
u8path()
应该处理 UTF-8 编码的
std::string
很好,并根据需要将其转换为文件系统的 native 编码。但是,不能保证底层文件系统实际上会处理像
Яyes.txt
这样的 Unicode 文件名。正确,但这将是操作系统问题,而不是 C++ 问题。
listfiles()
函数在使用
directory_iterator
时根本没有使用 UTF-8 .它是
sf::String
的类型转换来自
getcwd()
ANSI 编码
std::string
(这是有损转换),而不是 UTF-8 编码的
std::string
.但更糟糕的是,
sf::String
由
getcwd()
build 来自 UTF-8 编码的
std::string
但是
std::string
sf::String
的构造函数默认情况下需要 ANSI,而不是 UTF-8(要解决这个问题,你必须给它一个 UTF-8
std::locale
)。因此,您正在经历几次有损转换,试图从 std::filesystem::path
returned from
获取字符串。 std::filesystem::current_path
to
std::filesystem::directory_iterator`。
sf::String
可以转换到/从
std::wstring
, 其中
std::filesystem::path
也可以使用,所以不用经过UTF-8和
std::filesystem::u8path()
至少在
std::wstring
的 Windows 上使用 UTF-16 和 Windows 底层文件系统 API 也使用 UTF-16。
bool neaxfile::isfile(const str &file) {
std::wstring wstr = file;
std::wcout << L"\nThis: " << wstr << L"\n";
return std::filesystem::is_regular_file(std::filesystem::path(wstr));
}
str neaxfile::getcwd() {
std::error_code ec;
str path = std::filesystem::current_path(ec).wstring();
if (ec.value() == 0) {
return path;
} else {
return L"";
}
}
std::vector<str> neaxfile::listfiles() {
std::vector<str> res;
std::filesystem::path cwdpath(neaxfile::getcwd().wstring());
for (auto entry : std::filesystem::directory_iterator(cwdpath) {
str filepath = entry.path().wstring();
if (neaxfile::isfile(filepath)) res.push_back(filepath);
}
return res;
}
如果您真的想使用 UTF-8 在 C++ 字符串和 SFML 字符串之间进行转换,请尝试这样做以避免任何数据丢失:
std::string makeutf8str(const str &string) {
auto utf8 = string.toUtf8();
return std::string(reinterpret_cast<const char*>(utf8.c_str()), utf8.size());
}
str fromutf8str(const std::string &string) {
return str::fromUtf8(utf8.begin(), utf8.end());
}
bool neaxfile::isfile(const str &file) {
auto utf8 = makeutf8str(file);
std::cout << "\nThis: " << utf8 << "\n";
return std::filesystem::is_regular_file(std::filesystem::u8path(utf8));
}
str neaxfile::getcwd() {
std::error_code ec;
auto path = std::filesystem::current_path(ec).u8string();
if (ec.value() == 0) {
return fromutf8str(path);
} else {
return "";
}
}
std::vector<str> neaxfile::listfiles() {
std::vector<str> res;
auto cwdpath = std::filesystem::u8path(makeutf8str(neaxfile::getcwd()));
for (auto entry : std::filesystem::directory_iterator(cwdpath)) {
str filepath = fromutf8str(entry.path().u8string());
if (neaxfile::isfile(filepath)) res.push_back(filepath);
}
return res;
}
话虽如此,您在 C++ 字符串和 SFML 字符串之间进行了大量不必要的转换。当您不直接与 SFML 的 API 交互时,您真的不应该使用 SFML 字符串。您确实应该尽可能多地使用 C++ 字符串,尤其是使用
<filesystem>
API,例如:
bool neaxfile::isfile(const std::string &file) {
std::cout << L"\nThis: " << file << L"\n";
return std::filesystem::is_regular_file(std::filesystem::u8path(file));
}
std::string neaxfile::getcwd() {
std::error_code ec;
std::string path = std::filesystem::current_path(ec).u8string();
if (ec.value() == 0) {
return path;
} else {
return "";
}
}
std::vector<std::string> neaxfile::listfiles() {
std::vector<std::string> res;
auto cwdpath = std::filesystem::u8path(neaxfile::getcwd());
for (auto entry : std::filesystem::directory_iterator(cwdpath)) {
auto filepath = entry.path().u8string();
if (neaxfile::isfile(filepath)) res.push_back(filepath);
}
return res;
}
或者:
bool neaxfile::isfile(const std::wstring &file) {
std::wcout << L"\nThis: " << file << L"\n";
return std::filesystem::is_regular_file(std::filesystem::path(file));
}
std::wstring neaxfile::getcwd() {
std::error_code ec;
auto path = std::filesystem::current_path(ec).wstring();
if (ec.value() == 0) {
return path;
} else {
return L"";
}
}
std::vector<std::wstring> neaxfile::listfiles() {
std::vector<std::wstring> res;
std::filesystem::path cwdpath(neaxfile::getcwd());
for (auto entry : std::filesystem::directory_iterator(cwdpath)) {
auto filepath = entry.path().wstring();
if (neaxfile::isfile(filepath)) res.push_back(filepath);
}
return res;
}
更好的选择是根本不传递字符串。
std::filesystem::path
是一种抽象,可以帮助您避免这种情况,例如:
bool neaxfile::isfile(const std::filesystem::path &file) {
std::wcout << L"\nThis: " << file.wstring() << L"\n";
return std::filesystem::is_regular_file(file);
}
std::filesystem::path neaxfile::getcwd() {
std::error_code ec;
auto path = std::filesystem::current_path(ec);
if (ec.value() == 0) {
return path;
} else {
return {};
}
}
std::vector<std::filesystem::path> neaxfile::listfiles() {
std::vector<std::filesystem::path> res;
for (auto entry : std::filesystem::directory_iterator(neaxfile::getcwd())) {
auto filepath = entry.path();
if (neaxfile::isfile(filepath)) res.push_back(filepath);
}
return res;
}
关于c++ - 将 unicode sf::String 传递到 std::filesystem::u8path,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63175473/
我正在开发一个小型图书馆,我需要做的一件事是让访问者访问一些数据并返回结果。 在一些较旧的 C++ 代码中,访问者需要声明一个 typedef return_type .例如,boost::stati
我正在尝试使用std:map类型的键和值制作std::any Visual Studio 2017 std::map m("lastname", "Ivanov"); std::cout (m["la
我已经在 C++ 的 map 中声明了一个集合为 std::map> .如何循环访问或打印设定值? 最佳答案 如果你知道如何迭代 std::map或 std::set单独地,您应该可以毫无问题地组合迭
如何循环? 我已经试过了: //----- code std::vector >::iterator it; for ( it = users.begin(); it != users.end();
我有两个用例。 A.我想同步访问两个线程的队列。 B.我想同步两个线程对队列的访问并使用条件变量,因为其中一个线程将等待另一个线程将内容存储到队列中。 对于用例 A,我看到了使用 std::lock_
我正在查看这两种类型特征的文档,但不确定有什么区别。我不是语言律师,但据我所知,它们都适用于“memcpy-able”类型。 它们可以互换使用吗? 最佳答案 不,这些术语不能互换使用。这两个术语都表示
我有以下测试代码,其中有一个参数 fS,它是 ofstream 的容器: #include #include #include #include int
这是这个问题的延续 c++ function ptr in unorderer_map, compile time error 我试图使用 std::function 而不是函数指针,并且只有当函数是
std::unordered_map str_bool_map = { {"a", true}, {"b", false}, {"c", true} }; 我们可以在此映射上使
我有以下对象 std::vector> vectorList; 然后我添加到这个使用 std::vector vec_tmp; vec_tmp.push_back(strDRG); vec_tmp.p
为什么 std::initializer_list不支持std::get<> , std::tuple_size和 std::tuple_element ?在constexpr中用得很多现在的表达式,
我有一个像这样定义的变量 auto drum = std::make_tuple ( std::make_tuple ( 0.3f , Ex
假设我有一个私有(private)std::map在我的类(class)里std::map 。我怎样才能将其转换为std::map返回给用户?我想要下面的原型(prototype) const std
假设我有一个私有(private)std::map在我的类(class)里std::map 。我怎样才能将其转换为std::map返回给用户?我想要下面的原型(prototype) const std
问题 我正在尝试将 lambda 闭包传递给 std::thread,它使用任意封闭参数调用任意封闭函数。 template std::thread timed_thread(Function&& f
我想创建一个模板类,可以容纳容器和容器的任意组合。例如,std::vector或 std::map ,例如。 我尝试了很多组合,但我必须承认模板的复杂性让我不知所措。我编译的关闭是这样的: templ
我有一个 std::vector>我将其分配给相同类型的第二个 vector 。 我收到这个编译器错误: /opt/gcc-8.2.0/include/c++/8.2.0/bits/stl_algob
有时候,我们有一个工厂可以生成一个 std::unique_ptr vector ,后来我们想在类/线程/你命名的之间共享这些指针。因此,最好改用 std::shared_ptr 。当然有一种方法可以
这个问题在这里已经有了答案: Sorting a vector of custom objects (14 个答案) 关闭 6 年前。 我创建了一个 vector vector ,我想根据我定义的参
我有三个类(class)成员: public: std::vector > getObjects(); std::vector > getObjects() const; privat
我是一名优秀的程序员,十分优秀!