libCurl 使用 WriteFile WINAPI 写入数据
libCurl write data with WriteFile WINAPI
我使用 libcurl 从 Internet 下载数据。如果使用FILE写入下载的数据就可以了。但我想预先分配数据并写入它。我正在使用
使用前缀大小数据预分配文件。在那之后我使用 WriteFile 来写入下载的数据但没有成功。文件损坏或失败,无法打开或使用它。这是我的简单代码,任何人都知道修复 writeData 方法。谢谢大家
#include "stdafx.h"
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>
#include <conio.h>
#include <curl\curl.h>
using namespace std;
size_t writeData(void *buffer, size_t size, size_t nmemb, HANDLE *userdata){
BOOL bErrorFlag = FALSE;
bErrorFlag = WriteFile(
userdata, // open file handle
buffer, // start of data to write
(size*nmemb), // number of bytes to write
0, // number of bytes that were written
NULL);
return nmemb;
}
int progressData(void *ptr, double dltotal, double dlnow, double ultotal, double ulnow){
cout << "DOWNLOADED: " << dlnow / 1024 << "KB TOTAL SIZE: " << dltotal / 1024 << "KB" << endl;
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
CURL *curl;
FILE *fp;
CURLcode res;
string url = "http://myserver.allmedia.com/games/NgaoKiem300115/sampleFile.zip";
string save = "E:\Downloads\sampleFile.zip";
HANDLE file = CreateFile("E:\Downloads\sampleFile.zip", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (file == INVALID_HANDLE_VALUE){
cout << "ALLOCATE FILE FAIL" << endl;
}
SetFilePointer(file, 486702722, NULL, FILE_BEGIN);
SetEndOfFile(file);
curl = curl_easy_init();
if (curl){
fp = fopen(save.c_str(), "wb");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeData);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &file);
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progressData);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
system("pause");
return 0;
}
您没有执行太多的错误检查,所以谁知道可能出了什么问题?这是初学者在使用 Win32e 时最常犯的错误。如文档所述,始终检查错误。
查看您的代码,在开始写入文件之前,您没有将文件指针移回文件开头。仅此一项就意味着您的代码无法工作。也许还有更多错误,但我没有深入挖掘。
你最好进行一些调试。试图通过盯着代码解决问题并不总是成功。在程序执行时检查程序。了解如何调试。
你犯了很多错误:
您没有在预调整文件大小后将文件指针找回 0,因此您的写入将从文件末尾开始。
您正在通过指针将文件 HANDLE
传递给 writeData()
函数,这没问题,但是您在调用 WriteFile()
时并未取消引用该指针, 所以它总是会失败。
如果 WriteFile()
失败,您不会向 libCurl 报告错误。
您打开了同一个文件的多个不同类型的句柄,并且在完成下载后没有关闭任何一个句柄。
您将 string
而不是 char*
传递给 CURLOPT_URL
。
尝试更像这样的东西:
#include "stdafx.h"
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>
#include <conio.h>
#include <curl\curl.h>
using namespace std;
size_t writeData(void *buffer, size_t size, size_t nmemb, HANDLE *userdata)
{
DWORD dwWritten;
BOOL bResult = WriteFile(
*userdata, // open file handle
buffer, // start of data to write
(size*nmemb), // number of bytes to write
&dwWritten, // number of bytes that were written
NULL));
if (!bResult) {
return 0;
}
return dwWritten;
}
int progressData(void *ptr, double dltotal, double dlnow, double ultotal, double ulnow)
{
cout << "DOWNLOADED: " << dlnow / 1024 << "KB TOTAL SIZE: " << dltotal / 1024 << "KB" << endl;
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
CURL *curl;
CURLcode res;
string url = "http://myserver.allmedia.com/games/NgaoKiem300115/NgaoKiem.zip";
string save = "E:\Downloads\NgaoKiem.zip";
HANDLE file = CreateFileA(save.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (file == INVALID_HANDLE_VALUE) {
cout << "CREATE FILE FAIL, ERROR " << GetLastError() << endl;
goto done;
}
if (SetFilePointer(file, 486702722, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {
cout << "ALLOCATE FILE FAIL, ERROR " << GetLastError() << endl;
goto cleanup;
}
if (!SetEndOfFile(file)) {
cout << "ALLOCATE FILE FAIL, ERROR " << GetLastError() << endl;
goto cleanup;
}
if (SetFilePointer(file, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {
cout << "PREPARE FILE FAIL, ERROR " << GetLastError() << endl;
goto cleanup;
}
curl = curl_easy_init();
if (!curl) {
cout << "CURL INIT FAIL" << endl;
goto cleanup;
}
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeData);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &file);
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progressData);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);
res = curl_easy_perform(curl);
if (res != CURLE_OK) {
cout << "CURL DOWNLOAD FAIL, ERROR " << res << endl;
}
curl_easy_cleanup(curl);
cleanup:
CloseHandle(file);
done:
system("pause");
return 0;
}
我使用 libcurl 从 Internet 下载数据。如果使用FILE写入下载的数据就可以了。但我想预先分配数据并写入它。我正在使用
使用前缀大小数据预分配文件。在那之后我使用 WriteFile 来写入下载的数据但没有成功。文件损坏或失败,无法打开或使用它。这是我的简单代码,任何人都知道修复 writeData 方法。谢谢大家
#include "stdafx.h"
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>
#include <conio.h>
#include <curl\curl.h>
using namespace std;
size_t writeData(void *buffer, size_t size, size_t nmemb, HANDLE *userdata){
BOOL bErrorFlag = FALSE;
bErrorFlag = WriteFile(
userdata, // open file handle
buffer, // start of data to write
(size*nmemb), // number of bytes to write
0, // number of bytes that were written
NULL);
return nmemb;
}
int progressData(void *ptr, double dltotal, double dlnow, double ultotal, double ulnow){
cout << "DOWNLOADED: " << dlnow / 1024 << "KB TOTAL SIZE: " << dltotal / 1024 << "KB" << endl;
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
CURL *curl;
FILE *fp;
CURLcode res;
string url = "http://myserver.allmedia.com/games/NgaoKiem300115/sampleFile.zip";
string save = "E:\Downloads\sampleFile.zip";
HANDLE file = CreateFile("E:\Downloads\sampleFile.zip", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (file == INVALID_HANDLE_VALUE){
cout << "ALLOCATE FILE FAIL" << endl;
}
SetFilePointer(file, 486702722, NULL, FILE_BEGIN);
SetEndOfFile(file);
curl = curl_easy_init();
if (curl){
fp = fopen(save.c_str(), "wb");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeData);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &file);
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progressData);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
system("pause");
return 0;
}
您没有执行太多的错误检查,所以谁知道可能出了什么问题?这是初学者在使用 Win32e 时最常犯的错误。如文档所述,始终检查错误。
查看您的代码,在开始写入文件之前,您没有将文件指针移回文件开头。仅此一项就意味着您的代码无法工作。也许还有更多错误,但我没有深入挖掘。
你最好进行一些调试。试图通过盯着代码解决问题并不总是成功。在程序执行时检查程序。了解如何调试。
你犯了很多错误:
您没有在预调整文件大小后将文件指针找回 0,因此您的写入将从文件末尾开始。
您正在通过指针将文件
HANDLE
传递给writeData()
函数,这没问题,但是您在调用WriteFile()
时并未取消引用该指针, 所以它总是会失败。如果
WriteFile()
失败,您不会向 libCurl 报告错误。您打开了同一个文件的多个不同类型的句柄,并且在完成下载后没有关闭任何一个句柄。
您将
string
而不是char*
传递给CURLOPT_URL
。
尝试更像这样的东西:
#include "stdafx.h"
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>
#include <conio.h>
#include <curl\curl.h>
using namespace std;
size_t writeData(void *buffer, size_t size, size_t nmemb, HANDLE *userdata)
{
DWORD dwWritten;
BOOL bResult = WriteFile(
*userdata, // open file handle
buffer, // start of data to write
(size*nmemb), // number of bytes to write
&dwWritten, // number of bytes that were written
NULL));
if (!bResult) {
return 0;
}
return dwWritten;
}
int progressData(void *ptr, double dltotal, double dlnow, double ultotal, double ulnow)
{
cout << "DOWNLOADED: " << dlnow / 1024 << "KB TOTAL SIZE: " << dltotal / 1024 << "KB" << endl;
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
CURL *curl;
CURLcode res;
string url = "http://myserver.allmedia.com/games/NgaoKiem300115/NgaoKiem.zip";
string save = "E:\Downloads\NgaoKiem.zip";
HANDLE file = CreateFileA(save.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (file == INVALID_HANDLE_VALUE) {
cout << "CREATE FILE FAIL, ERROR " << GetLastError() << endl;
goto done;
}
if (SetFilePointer(file, 486702722, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {
cout << "ALLOCATE FILE FAIL, ERROR " << GetLastError() << endl;
goto cleanup;
}
if (!SetEndOfFile(file)) {
cout << "ALLOCATE FILE FAIL, ERROR " << GetLastError() << endl;
goto cleanup;
}
if (SetFilePointer(file, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {
cout << "PREPARE FILE FAIL, ERROR " << GetLastError() << endl;
goto cleanup;
}
curl = curl_easy_init();
if (!curl) {
cout << "CURL INIT FAIL" << endl;
goto cleanup;
}
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeData);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &file);
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progressData);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);
res = curl_easy_perform(curl);
if (res != CURLE_OK) {
cout << "CURL DOWNLOAD FAIL, ERROR " << res << endl;
}
curl_easy_cleanup(curl);
cleanup:
CloseHandle(file);
done:
system("pause");
return 0;
}