C++ 如何在c+中将utf-8转换为ASCII+;?
我收到来自utf-8服务器的响应,但无法读取该响应。C++ 如何在c+中将utf-8转换为ASCII+;?,c++,C++,我收到来自utf-8服务器的响应,但无法读取该响应。 如何在C++中转换UTF-8到ASCII?< P> UTF-8与ASCII向后兼容,意味着在UTF-8中所有ASCII字符都被编码为单个未改变字节值。如果文本应为ASCII,但您无法读取,则肯定存在另一个问题。UTF-8是一种可以映射每个unicode字符的编码。ASCII仅支持非常小的unicode子集 对于作为ASCII的unicode子集,从UTF-8到ASCII的映射是直接的一对一字节映射,因此,如果服务器向您发送的文档仅包含UTF-
如何在C++中转换UTF-8到ASCII?< P> UTF-8与ASCII向后兼容,意味着在UTF-8中所有ASCII字符都被编码为单个未改变字节值。如果文本应为ASCII,但您无法读取,则肯定存在另一个问题。UTF-8是一种可以映射每个unicode字符的编码。ASCII仅支持非常小的unicode子集 对于作为ASCII的unicode子集,从UTF-8到ASCII的映射是直接的一对一字节映射,因此,如果服务器向您发送的文档仅包含UTF-8编码的ASCII字符,则您可以直接将其读取为ASCII
如果响应包含非ASCII字符,那么无论您做什么,都无法用ASCII来表示它们。要从UTF-8流中过滤这些数据,只需过滤掉任何>=128(0x80十六进制)的字节。首先请注意,ASCII是一种7位格式。有8位编码,如果您要使用其中一种(如ISO 8859-1),则需要更加具体 要将ASCII字符串转换为UTF-8,请不要执行任何操作:它们是相同的。因此,如果您的UTF-8字符串仅由ASCII字符组成,那么它已经是ASCII字符串,不需要进行转换 如果UTF-8字符串包含非ASCII字符(任何带有重音或非拉丁字符的字符),则无法将其转换为ASCII。(您也许可以将其转换为一种ISO编码。)
有一些方法可以从拉丁字符中去除重音,以至少在ASCII中获得一些相似之处。或者,如果您只想删除非ASCII字符,只需从utf-8字符串中删除值>=128的所有字节。如果字符串包含ASCII中不存在的字符,则您无法执行任何操作,因为这些字符在ASCII中不存在 如果字符串仅包含ASCII中存在的字符,则无需执行任何操作,因为字符串已经采用ASCII编码:UTF-8专门设计为向后兼容ASCII,因此任何ASCII字符在UTF-8中的编码都与ASCII中的编码完全相同,任何非ASCII字符的编码都不能是有效的ASCII,也就是说,任何非ASCII字符都将被编码为2–4个八位字节的序列,所有八位字节都有其最高有效位集,即整数值大于127) 您可以尝试对字符串进行音译,而不是简单地转换字符串。这个星球上的大多数语言都有某种形式的ASCII音译方案,至少可以让文本在某种程度上易于理解。例如,我的名字是“Jörg”,它的ASCII音译是“Joerg”。Ruby编程语言的创建者的名字是“まつもとゆきひろ" 其ASCII音译为“Matsumoto Yukihiro”。但是,请注意,您将丢失信息。例如,德语sz连字被音译为“ss”,因此单词“Maße”(测量值)被音译为“Masse”。然而,“Masse”(物理学家认为的质量,而非基督徒认为的质量)也是一个单词。另一个例子是,土耳其语有4个“i”(小写和大写,带点和不带点),而ASCII只有2个(小写和不带点,大写和不带点),因此您将丢失关于点的信息,或者它是否是大写字母 因此,唯一不会丢失信息的方法(换句话说:损坏的数据),是以某种方式将非ASCII字符编码为ASCII字符序列。有许多流行的编码方案:SGML实体引用、MIME、Unicode转义序列、ΕΧ或LaΕΧ。因此,您可以在数据进入系统时对其进行编码,并在数据离开系统时对其进行解码
当然,最简单的方法是简单地修复您的系统。ASCII是一个表示128个字符和控制代码的代码页,其中utf8能够表示Unicode标准中的任何字符,这比ASCII功能多得多。 所以你的问题的答案是:不可能
除非您有更多的数据源规范。检查此项,忘记将其转换为ASCII。此示例适用于Windows(您没有提到您的目标操作系统): 当不再需要时,记得
删除[]宽;
和/或ansi
。由于这是unicode,我建议坚持使用wchar\u t*
而不是char*
,除非您确定输入缓冲区包含属于同一ansi子集的字符。关于短语
如果字符串包含ASCII中不存在的字符,则您无能为力,因为ASCII中不存在这些字符
这是错误的
UTF-8是多字节代码集,可能需要2组以上的符号(语言)。实际上,您可以使用单一语言(通常为英语)或两种语言,其中一种是英语
- 第一种情况是简单的ASCII字符(任何编码)
- 第二个描述ASCII字符对应编码。如果不是中文或阿拉伯语
在上述条件下,可以将UTF-8转换为ASCII字符,相应的功能在C++中是不存在的,因此可以手动完成。很容易检测到1字节的两字节符号。第一字节的高位设置为两字节的字节,否则不设置。
< P>注意:有两个代码< UTF8< /C> >:UTF8IY带有UBFM和UTF8IO。M.并且您需要在转换为ANSI
时对它们进行不同的处理
- UTF8_,材料清单符合ANSI标准
- UTF8_无需符合ANSI标准
// The sample buffer contains "©ha®a©te®s" in UTF-8
unsigned char buffer[15] = { 0xc2, 0xa9, 0x68, 0x61, 0xc2, 0xae, 0x61, 0xc2, 0xa9, 0x74, 0x65, 0xc2, 0xae, 0x73, 0x00 };
// utf8 is the pointer to your UTF-8 string
char* utf8 = (char*)buffer;
// convert multibyte UTF-8 to wide string UTF-16
int length = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)utf8, -1, NULL, 0);
if (length > 0)
{
wchar_t* wide = new wchar_t[length];
MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)utf8, -1, wide, length);
// convert it to ANSI, use setlocale() to set your locale, if not set
size_t convertedChars = 0;
char* ansi = new char[length];
wcstombs_s(&convertedChars, ansi, length, wide, _TRUNCATE);
}
void change_encoding_from_UTF8_with_BOM_to_ANSI(const char* filename)
{
ifstream infile;
string strLine="";
string strResult="";
infile.open(filename);
if (infile)
{
// the first 3 bytes (ef bb bf) is UTF-8 header flags
// all the others are single byte ASCII code.
// should delete these 3 when output
getline(infile, strLine);
strResult += strLine.substr(3)+"\n";
while(!infile.eof())
{
getline(infile, strLine);
strResult += strLine+"\n";
}
}
infile.close();
char* changeTemp=new char[strResult.length()];
strcpy(changeTemp, strResult.c_str());
char* changeResult = change_encoding_from_UTF8_to_ANSI(changeTemp);
strResult=changeResult;
ofstream outfile;
outfile.open(filename);
outfile.write(strResult.c_str(),strResult.length());
outfile.flush();
outfile.close();
}
// change a char's encoding from UTF8 to ANSI
char* change_encoding_from_UTF8_to_ANSI(char* szU8)
{
int wcsLen = ::MultiByteToWideChar(CP_UTF8, NULL, szU8, strlen(szU8), NULL, 0);
wchar_t* wszString = new wchar_t[wcsLen + 1];
::MultiByteToWideChar(CP_UTF8, NULL, szU8, strlen(szU8), wszString, wcsLen);
wszString[wcsLen] = '\0';
int ansiLen = ::WideCharToMultiByte(CP_ACP, NULL, wszString, wcslen(wszString), NULL, 0, NULL, NULL);
char* szAnsi = new char[ansiLen + 1];
::WideCharToMultiByte(CP_ACP, NULL, wszString, wcslen(wszString), szAnsi, ansiLen, NULL, NULL);
szAnsi[ansiLen] = '\0';
return szAnsi;
}
void change_encoding_from_UTF8_without_BOM_to_ANSI(const char* filename)
{
ifstream infile;
string strLine="";
string strResult="";
infile.open(filename);
if (infile)
{
while(!infile.eof())
{
getline(infile, strLine);
strResult += strLine+"\n";
}
}
infile.close();
char* changeTemp=new char[strResult.length()];
strcpy(changeTemp, strResult.c_str());
char* changeResult = change_encoding_from_UTF8_to_ANSI(changeTemp);
strResult=changeResult;
ofstream outfile;
outfile.open(filename);
outfile.write(strResult.c_str(),strResult.length());
outfile.flush();
outfile.close();
}