我想你要使用writedata
并记得关闭文件
library(RCurl)
filename <- tempfile()
f <- CFILE(filename, "wb")
url <- "http://cran.fhcrc.org/Rlogo.jpg"
curlPerform(url = url, writedata = f@ref)
close(f)
对于更详细的写作,我不确定这是否是最好的方式,但 Linux 告诉我,从
man curl_easy_setopt
有一个 curl 选项 CURL_WRITEFUNCTION 它是一个指向带有原型的 C 函数的指针
size_t function(void *ptr, size_t size, size_t nmemb, void *stream);
在 ?curlPerform 末尾的 R 中有一个调用 C 函数作为“writefunction”选项的示例。所以我创建了一个文件 curl_writer.c
#include <stdio.h>
size_t
writer(void *buffer, size_t size, size_t nmemb, void *stream)
{
fprintf(stderr, "<writer> size = %d, nmemb = %d\n",
(int) size, (int) nmemb);
return size * nmemb;
}
编译它
R CMD SHLIB curl_writer.c
在 Linux 上生成一个文件 curl_writer.so,然后在 R
dyn.load("curl_writer.so")
writer <- getNativeSymbolInfo("writer", PACKAGE="curl_writer")$address
curlPerform(URL=url, writefunction=writer)
并上 stderr
<writer> size = 1, nmemb = 2653
<writer> size = 1, nmemb = 520
OK
这两个想法可以整合,即使用任意函数写入任意文件,通过修改C函数使用我们传入的FILE *,如
#include <stdio.h>
size_t
writer(void *buffer, size_t size, size_t nmemb, void *stream)
{
FILE *fout = (FILE *) stream;
fprintf(fout, "<writer> size = %d, nmemb = %d\n",
(int) size, (int) nmemb);
fflush(fout);
return size * nmemb;
}
然后在编译后返回 R
dyn.load("curl_writer.so")
writer <- getNativeSymbolInfo("writer", PACKAGE="curl_writer")$address
f <- CFILE(filename <- tempfile(), "wb")
curlPerform(URL=url, writedata=f@ref, writefunction=writer)
close(f)
getURL
也可以在这里使用,前提是writedata=f@ref, write=writer
;我认为原始问题中的问题R_curl_write_binary_data
实际上是一个内部函数,写入由 RCurl 管理的缓冲区,而不是像CFILE
. 同样,指定writedata
without write
(从源代码看来 getURL 是 writefunction 的别名)将指向文件的指针发送到期望指向其他指针的函数;对于 getURL,需要提供 writedata 和 write。