无法从Web服务器读取utf-8缓冲区

问题描述 投票:0回答:1

我正在用C ++编写一个简单的Web爬虫。

它连接到Web服务器并发送“GET”请求,然后它从Web服务器接收回复。

这是我用来执行此操作的代码段:

CHttpHeader reqHeader = websock.GenerateRequestHeader(url, nullptr);
dwResponse = websock.SendRequest(url, reqHeader, nullptr, nullptr);
if (dwResponse == 0)    {
    //::MessageBoxA(this->GetSafeHwnd(), "error to send http request", 0, 0);
    return;
}

//char*strstr = "병맛메로나";

//  Receive Response
const int bufferSize = 1024 * 1024 * 1;
char * buffer = new char[bufferSize * 10];
char *tbuffer = new char[bufferSize];

int recvLen = 0;
DWORD dwNextOffset = 0;


//setlocale(LC_ALL, "");

while (websock.HasMoreResponse())   {
    recvLen = websock.Recv(tbuffer, bufferSize);

    ::memcpy(buffer + dwNextOffset, tbuffer, recvLen);
    dwNextOffset+= recvLen;
}

服务器回复将被复制到buffer,长度为dwNextOffset

每件事都可以正常连接到服务器并正确接收回复。但是,在某些情况下使用UTF-8编码的回复,我无法从缓冲区中读取HTML标记。这一切都是胡言乱语。

我想这是由于客户端/服务器操作系统的差异。因为我在Windows上,当Web服务器是IIS(很可能在Windows上运行)时,读取UTF-8编码字符没有问题。但是,在Apache的某些情况下,会出现此问题。

操作系统之间的UTF-8格式是否不同?

如果是这样,我可以正确转换为MBCS吗?


编辑:这是文件保存部分:

FILE* fp = nullptr;
::fopen_s(&fp, "result", "wb");
::fwrite(buffer, 1, dwOffset, fp);
::fclose(fp);

结果是......

HTTP/1.1 200 OK
Date: Tue, 27 Feb 2018 12:19:19 GMT
X-UA-Compatible: IE=10
Expires: Sat, 01, Jan 1970 22:00:00 GMT
Pragma: no-cache
Cache-Control: no-cache, no-store, must-revalidate
P3P: CP="ALL DSP COR MON LAW IVDi HIS IVAi DELi SAMi OUR LEG PHY UNI ONL DEM STA INT NAV PUR FIN OTC GOV"
Content-Type: text/html;charset=UTF-8
Content-Language: ko-KR
Vary: Accept-Encoding
Content-Encoding: gzip
X-UA-Device-Type: pc
Content-Length: 49043
Connection: close

?      醬??/影?-~퍏뙗*쿭돃?긥먉^...

编辑:Max Vollmer,你是对的。在请求中使用Accept-Encoding : identity解决了一些问题。但还有另一个问题。

如果我使用此代码:

char *strstr = "병맛메로나";
std::string tstr(strstr);

tstr工作正常。

但是,如果我把buffer变成std::string,它又会有胡言乱语。

std::string tstr(buffer);

为什么会这样?

c++ utf-8
1个回答
4
投票

你的第一个问题,压缩:

Content-Encoding: gzip

您的数据已压缩,您必须将其解压缩。见Content-Encoding。这样做有很多C ++库。

或者,您可以根据您的请求发送Accept-Encoding: identity标头,因此服务器不会发送压缩数据。见Accept-Encoding

你的第二个问题,编码:

如果缓冲区是UTF-8编码,你不能只做std::string tstr(buffer);。首先,这根本不解码任何UTF-8字符。您甚至没有告诉它您的数据是UTF-8编码的,它应该如何知道?其次,任何需要超过8个字节的字符都不能用单个char表示,而std :: string使用char作为其字符,因此std::string永远不能保存UTF-8编码数据的文本表示。

你可能会对char究竟是什么感到困惑。它是一个8位大小的整数。

由于UTF-8使用多个字节对特殊字符进行编码,因此这些字符将存储在char数组中的多个字符中。当您使用该char数组创建一个std::string时,它只会将每个char解释为一个字符,这是错误的。

您必须将UTF-8数据解码为多字节字符串,例如std::wstring,或使用一些第三方库提供一些支持UTF-8开箱即用的字符串类。或者只是将数据写入文件并使用支持UTF-8的文本编辑器打开该文件,它应该自动检测编码。真的取决于你想要做什么。

这是将UTF-8编码数据转换为std::wstring的简单方法:

std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
std::wstring text = converter.from_bytes(buffer);
© www.soinside.com 2019 - 2024. All rights reserved.