我在打开UTF-8路径文件时遇到了问题。具有UTF-8字符(如西里尔语或拉丁语)的路径。我找到了一种用_wfopen
来解决这个问题的方法,但是当我用UTF手工编码UTF-8字符(\ Uxxxx)时解决它的方式。
是否有函数,宏或任何当我提供字符串(路径)时它将返回Unicode? p>
这样的事情: https://www.branah.com/unicode-converter
我尝试使用MultiByteToWideChar
,但它会返回一些不相关的十六进制数字。
尝试:
std::wstring s2ws(const std::string& s)
{
int len;
int slength = (int)s.length() + 1;
len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
wchar_t* buf = new wchar_t[len];
MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
std::wstring r(buf);
delete[] buf;
return r;
}
std::wstring stemp = s2ws(x);
LPCWSTR result = stemp.c_str();
我得到的结果:0055F7E8
提前谢谢
我安装了boost,现在我正在尝试使用boost。有人可以帮助我提升。
所以我有一条路:
wchar_t path[100] = _T("čaćšžđ\\test.txt");
我需要将它转换为:
wchar_t s[100] = _T("\u010d\u0061\u0107\u0161\u017e\u0111\\test.txt");
答案 0 :(得分:1)
这是一种在Windows上转换UTF-8和UTF-16的方法,以及显示输入和输出的存储代码单元的实际值:
#include <codecvt>
#include <iostream>
#include <iomanip>
#include <string>
int main() {
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> convert;
std::string s = "test";
std::cout << std::hex << std::setfill('0');
std::cout << "Input `char` data: ";
for (char c : s) {
std::cout << std::setw(2) << static_cast<unsigned>(static_cast<unsigned char>(c)) << ' ';
}
std::cout << '\n';
std::wstring ws = convert.from_bytes(s);
std::cout << "Output `wchar_t` data: ";
for (wchar_t wc : ws) {
std::cout << std::setw(4) << static_cast<unsigned>(wc) << ' ';
}
std::cout << '\n';
}
了解输入和输出的实际值很重要,否则您可能无法正确理解您真正需要的转换。例如,在我看来,对于VC ++如何处理编码以及\Uxxxxxxxx
和\uxxxx
在C ++源代码中实际执行的操作(例如,它们不一定产生UTF-)可能存在一些混淆。 8数据)。
尝试使用上面显示的代码来查看输入数据的真实含义。
强调我上面所写的内容;有强烈的迹象表明您可能无法正确理解输入上正在进行的处理,您需要对其进行彻底检查。
如果用以下内容替换测试字符串,上述程序会将ć(U + 0107)的UTF-8表示正确转换为单个16位代码单元0x0107
:
std::string s = "\xC4\x87"; // UTF-8 representation of U+0107
然后在Windows上使用Visual Studio输出程序:
输入
char
数据:c4 87
输出wchar_t
数据:0107
这与使用测试字符串形成对比,例如:
std::string s = "ć";
或者
std::string s = "\u0107";
这可能会导致以下输出:
输入
char
数据:3f
输出wchar_t
数据:003f
这里的问题是Visual Studio不使用UTF-8作为字符串的编码而没有一些技巧,所以你从UTF-8转换的请求可能不是你真正需要的;或者您确实需要从UTF-8转换,但是您正在使用与实际输入不同的输入来测试潜在的转换例程。
所以我有一条路径:wchar_t path [100] = _T(“čaćšžđ\ test.txt”);
我需要将它转换为:
wchar_t s [100] = _T(“\ u010d \ u0061 \ u0107 \ u0161 \ u017e \ u0111 \ test.txt”);
好的,如果我理解正确,你的实际问题是以下失败:
wchar_t path[100] = _T("čaćšžđ\\test.txt");
FILE *f = _wfopen(path, L"w");
但是如果你改写字符串就像:
wchar_t path[100] = _T("\u010d\u0061\u0107\u0161\u017e\u0111\\test.txt");
然后_wfopen
调用成功并打开您想要的文件。
首先,这与UTF-8完全无关。我假设您找到了一些使用char
字符串并将其转换为wchar_t
的解决方法,并且您以某种方式将其解释为涉及UTF-8或其他内容。
您使用哪种编码保存源代码?字符串L"čaćšžđ\\test.txt"
实际上是否正确保存?尝试关闭源文件并重新打开它。如果某些字符显示为?
,则部分问题是源文件编码。特别是Windows在大多数北美和西欧使用的默认编码都是如此:“西欧(Windows) - 代码页1252”。
您还可以检查以下程序的输出:
#include <iomanip>
#include <iostream>
int main() {
wchar_t path[16] = L"čaćšžđ\\test.txt";
std::cout << std::hex << std::setfill('0');
for (wchar_t wc : path) {
std::cout << std::setw(4) << static_cast<unsigned>(wc) << ' ';
}
std::cout << '\n';
wchar_t s[16] = L"\u010d\u0061\u0107\u0161\u017e\u0111\\test.txt";
for (wchar_t wc : s) {
std::cout << std::setw(4) << static_cast<unsigned>(wc) << ' ';
}
std::cout << '\n';
}
您需要了解的另一件事是\uxxxx
写字符形式(称为通用字符名称或UCN)不是可以在C ++中将字符串转换为字符串的表单。当您编译程序并且它正在运行时,即当您编写的任何代码可能正在尝试生成包含\uxxxx
的字符串时,编译器将UCN解释为不同字符的时间早已过去。唯一可行的UCN是直接写在源文件中的。
另外,您错误地使用了_T()
。 IMO您根本不应该使用TCHAR
和相关的宏,但是如果您确实使用它,那么您应该始终如一地使用它:不要混淆TCHAR
API并明确使用* W API或wchar_t
。 TCHAR
的重点是允许代码独立并在wchar_t
和Microsoft的“ANSI”API之间切换,因此使用TCHAR
然后硬编码{{1}的假设} TCHAR
击败了整个目的。
你应该写:
wchar_t
答案 1 :(得分:0)
问题是我将CPP文件保存为ANSI ...我必须将其转换为UTF-8。我在发布之前试过这个,但是VS 2015把它变成了ANSI,我不得不在VS中改变它,所以我可以让它工作。
我尝试用notepad ++打开cpp文件并更改编码但是当我打开VS时它会自动返回。所以我期待Save As
选项,但没有编码选项。最后我在Visual Studio 2015中找到了它
文件 - &gt; “编码”下拉列表中的“高级保存选项”将其更改为Unicode
有一点对我来说仍然很奇怪,VS是如何正常显示字符的,但当我在N ++中打开文件时,有?(因为它应该是因为ANSI)?
答案 2 :(得分:0)
您的代码是特定于Windows的,并且您使用的是Visual C ++。所以,只需使用宽文字。 Visual C ++支持文件流构造函数的宽字符串。
就这么简单 - 当你不需要携带时。
#include <fstream>
#include <iostream>
#include <stdlib.h>
using namespace std;
auto main() -> int
{
wchar_t const path[] = L"cacšžd/test.txt";
ifstream f( path );
int ch;
while( (ch = f.get()) != EOF )
{
cout.put( ch );
}
}
但请注意,此代码是特定于Visual C ++的。这对于特定于Windows的代码来说是合理的。可能使用C ++ 17,我们将Boost文件系统库采用到标准库中,然后为了符合性,g ++将理想地提供此处使用的构造函数。