我正在使用boost :: asio从服务器获得响应。结果存储在std :: string中。
我想将此std :: string转换为.png图像并将其写入文件。
我遇到了这个问题。这是我的代码:
CURL *curl;
CURLcode res;
std::string errorBuffer[CURL_ERROR_SIZE];
std::string url="http://www.google.ie/images/srpr/logo3w.png";
std::string response="";
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_HEADER, 0);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(curl, CURLOPT_ENCODING, "gzip");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_to_string);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
res=curl_easy_perform(curl);
curl_easy_cleanup(curl);
现在存储在response
write_to_binary_file(response.data());
,其中write_to_binary_file为:
void write_to_binary_file(std::string p_Data){
//std::fstream binary_file("./img.png",std::ios::out|std::ios::binary|std::ios::app);
//binary_file.write(reinterpret_cast<const char*>(&p_Data),sizeof(std::string));
//binary_file.close();
std::ofstream file("img.png", std::ios::binary);
file.write(p_Data,sizeof(p_Data));
file.close();
}
现在,如果我对我的C ++程序写的文件进行八进制转储,那么当我直接从URL下载文件时,它与八进制转储完全不同。
更新了write_to_binary_file
int write_to_binary_file(const char* p_Data){
//std::fstream binary_file("./img.png",std::ios::out|std::ios::binary|std::ios::app);
//binary_file.write(reinterpret_cast<const char*>(&p_Data),sizeof(std::string));
//binary_file.write(c_str(),sizeof(ring));
//binary_file.close();
/*std::ofstream file("img.png", std::ios::binary);
file.write(p_Data,len);
file.close();*/
FILE *fp;
size_t count;
const char *str = p_Data;
fp = fopen("img.png", "w");
if(fp == NULL) {
perror("failed to open img.png");
return EXIT_FAILURE;
}
count = fwrite(str, 1, strlen(str), fp);
printf("Wrote %zu bytes. fclose(fp) %s.\n", count, fclose(fp) == 0 ? "succeeded" : "failed");
return EXIT_SUCCESS;
}
使用int x=write_to_binary_file(response.c_str());
仍然不适合我;(
答案 0 :(得分:3)
binary_file.write(reinterpret_cast<const char*>(&p_Data),sizeof(std::string));
是的,这就是reinterpret_cast
在许多情况下很差的原因:它促进了 guesscoding 。
这是当你抛弃你的参考资料而只是假设你需要将指针传递到某个地方的std::string
时,并确定编译器的错误消息是错误的。所以,你使用reinterpret_cast
“关闭它”,现在你想知道为什么没有什么工作正常。
据推测,有人告诉你“使用std::string
”代替char数组,而你刚刚交换了类型名称而不是对实际差异进行任何研究。
std::string
是一个具有各种内部成员的对象,它通常间接地存储它的实际字符串数据(动态地,或者你可能不准确和误导地称为“在堆上”);实际上,它完全是从你那里抽象出来的,只是它如何存储它的数据。无论哪种方式,它不仅仅是char
数组。
使用它提供的API获取指向char
数组的指针,其中包含std::string::data()
或可能std::string::c_str()
...和stop guesscoding。
另外,我怀疑这会编译:
std::string errorBuffer[CURL_ERROR_SIZE];
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
你可能想构建一个具有一定长度的std::string
:
std::string errorBuffer(CURL_ERROR_SIZE);
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &errorBuffer[0]);
// ^ (requires C++11 to be completely safe)
字符串是对象,而不是原始数组!
答案 1 :(得分:1)
我的第一个猜测是“reinterpret_cast(&amp; p_Data)” 弄乱了你的数据。你为什么用这种方式施展它? p_Data.data()或p_Data.c_str()可能就是你想要的。
答案 2 :(得分:1)
您可能需要考虑将SFML用于此类任务,并给它deals with HTTP并大大简化任务。我个人用它从网站上下载.GIF图片。
为了解决你的问题(我确实不熟悉boost :: asio),你需要考虑的事情是:
不要做sizeof(std :: string)。 Std :: string有一个.size()方法。所以response.size();适用于此。
在处理来自网站的原始数据时,不要使用strlen(),sizeof()或任何使用以null结尾的sentinel值的方法,因为可以在任何地方出现> 在原始数据流中(它不像文本)。使用std :: string的.size()方法。
鉴于它的原始数据,以二进制模式写入!文本模式将终止于Windows上文件中的ctrl + z信号。 IE可能无法完全写入文件。
Base64并不总是适用。无论如何,这可能是自动化的。
考虑从提供的URL本身中提取文件名。
假设响应可以接受,这就是您想要的代码:
FILE * File = NULL;
File = fopen("Image.png","wb"); //Note b for binary mode
if(File == NULL){return 1;} //Error
if(fwrite(response.c_str(),response.size(),1,File) != response.size()) //If there is a mismatch between the amount of data written and the string size, we have an error
{
perror("File write error occurred"); //Needs errno
fclose(File);
return 2;
}
fclose(File);
答案 3 :(得分:-1)
查看响应字符串的内容。 可能你应该在写入文件
之前用base64解码器解码它