我的软件的要求是包含导出数据的文件的编码应为UTF8。但是当我将数据写入文件时,编码总是ANSI。 (我使用Notepad ++来检查这个。)
我目前正在尝试通过阅读手动转换文件,将其转换为UTF8并将文本写入新文件。
line
是std::string
inputFile
是std::ifstream
pOutputFile
是FILE*
// ...
if( inputFile.is_open() )
{
while( inputFile.good() )
{
getline(inputFile,line);
//1
DWORD dwCount = MultiByteToWideChar( CP_ACP, 0, line.c_str(), -1, NULL, 0 );
wchar_t *pwcharText;
pwcharText = new wchar_t[ dwCount];
//2
MultiByteToWideChar( CP_ACP, 0, line.c_str(), -1, pwcharText, dwCount );
//3
dwCount = WideCharToMultiByte( CP_UTF8, 0, pwcharText, -1, NULL, 0, NULL, NULL );
char *pText;
pText = new char[ dwCount ];
//4
WideCharToMultiByte( CP_UTF8, 0, pwcharText, -1, pText, dwCount, NULL, NULL );
fprintf(pOutputFile,pText);
fprintf(pOutputFile,"\n");
delete[] pwcharText;
delete[] pText;
}
}
// ...
不幸的是,编码仍然是ANSI。我搜索了一段时间寻找解决方案,但我总是通过MultiByteToWideChar和WideCharToMultiByte遇到解决方案。但是,这似乎不起作用。我在这里缺少什么?
我也在这里寻找解决方案,但大多数UTF8问题涉及C#和php的东西。
答案 0 :(得分:2)
在VC ++ 2010的Windows上,使用本地化facet std :: codecvt_utf8_utf16(即在C ++ 11中),有可能(目前尚未在GCC中实现)。来自cppreference.com的示例代码包含读取/写入UTF-8文件所需的所有基本信息。
std::wstring wFromFile = _T("teststring");
std::wofstream fileOut("textOut.txt");
fileOut.imbue(std::locale(fileOut.getloc(), new std::codecvt_utf8_utf16<wchar_t>));
fileOut<<wFromFile;
它将ANSI编码文件设置为UTF-8(在记事本中检查)。希望这就是你所需要的。
答案 1 :(得分:1)
在Windows上,文件没有编码。每个应用程序将根据自己的规则采用编码。您可以做的最好的事情是在文件的前面放置byte-order mark并希望它被识别。
答案 2 :(得分:0)
AFAIK,fprintf()
进行字符转换,因此无法保证将UTF-8编码数据传递给它实际上会将UTF-8写入文件。由于您已经自己转换了数据,因此请使用fwrite()
,以便按原样编写UTF-8数据,例如:
DWORD dwCount = MultiByteToWideChar( CP_ACP, 0, line.c_str(), line.length(), NULL, 0 );
if (dwCount == 0) continue;
std::vector<WCHAR> utf16Text(dwCount);
MultiByteToWideChar( CP_ACP, 0, line.c_str(), line.length(), &utf16Text[0], dwCount );
dwCount = WideCharToMultiByte( CP_UTF8, 0, &utf16Text[0], utf16Text.size(), NULL, 0, NULL, NULL );
if (dwCount == 0) continue;
std::vector<CHAR> utf8Text(dwCount);
WideCharToMultiByte( CP_UTF8, 0, &utf16Text[0], utf16Text.size(), &utf8Text[0], dwCount, NULL, NULL );
fwrite(&utf8Text[0], sizeof(CHAR), dwCount, pOutputFile);
fprintf(pOutputFile, "\n");
答案 3 :(得分:0)
类型char
没有任何编码的线索,它所能做的只是存储8位。因此,任何文本文件都只是一个字节序列,用户必须猜测基础编码。以BOM表开头的文件表示UTF 8,但不建议再使用BOM表。相反,在Windows中,类型wchar_t
总是解释为UTF 16。
因此,假设您有一个用UTF 8编码的文件,只有一行:“孔子说:Smile。孔子说:微笑!?。”以下代码段再次将此文本追加,然后读取第一行并将其显示在MessageBoxW
和MessageBoxA
中。请注意,MessageBoxW
显示正确的文本,而MessageBoxA
显示一些垃圾,因为它假定我的本地代码页1252用于char*
字符串。
请注意,我使用了方便的CA2W
类而不是MultiByteToWideChar
。请注意,CP_Whatever
参数是可选的,如果省略,则使用本地代码页。
#include <iostream>
#include <fstream>
#include <filesystem>
#include <atlbase.h>
int main(int argc, char** argv)
{
std::fstream afile;
std::string line1A = u8"Confucius says: Smile. 孔子说:微笑! ?";
std::wstring line1W;
afile.open("Test.txt", std::ios::out | std::ios::app);
if (!afile.is_open())
return 0;
afile << "\n" << line1A;
afile.close();
afile.open("Test.txt", std::ios::in);
std::getline(afile, line1A);
line1W = CA2W(line1A.c_str(), CP_UTF8);
MessageBoxW(nullptr, line1W.c_str(), L"Smile", 0);
MessageBoxA(nullptr, line1A.c_str(), "Smile", 0);
afile.close();
return 0;
}