C++ 如何在c+中将utf-8转换为ASCII+;?

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-

我收到来自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-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标准


所有字符都是单字节ASCII字符吗?不知道。我知道
    // 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();
}