转载地址:http://blog.chinaunix.net/u/17660/showart_1822514.html
2 LibCurl编程
2.1 LibCurl编程流程
在基于LibCurl的程序里,主要采用callback function (回 调函数)的形式完成传输任务,用户在启动传输前设置好各类参数和回调函数,当满足条件时libcurl将调用用户的回调函数实现特定功能。下面是利用libcurl完成传输任务的流程:
1. 调用curl_global_init()初始化libcurl
2. 调用 curl_easy_init()函数得到 easy interface型指针
3. 调用curl_easy_setopt设置传输选项
4. 根据curl_easy_setopt设置的传输选项,实现回调函数以完成用户特定任务
5. 调用curl_easy_perform()函数完成传输任务
6. 调用curl_easy_cleanup()释放内存
在整过过程中设置curl_easy_setopt()参数是最关键的,几乎所有的libcurl程序都要使用它。
2.2 重要函数
1.CURLcode curl_global_init(long flags);

描述:
这个函数只能用一次。(其实在调用curl_global_cleanup 函数后仍然可再用)
如果这个函数在curl_easy_init函数调用时还没调用,它讲由libcurl库自动完成。
参数:flags
CURL_GLOBAL_ALL //初始化所有的可能的调用。
CURL_GLOBAL_SSL //初始化支持 安全套接字层。
CURL_GLOBAL_WIN32 //初始化win32套接字库。
CURL_GLOBAL_NOTHING //没有额外的初始化。

2 void curl_global_cleanup(void);
描述:在结束libcurl使用的时候,用来对curl_global_init做的工作清理。类似于close的函数。
3 char *curl_version( );
描述: 打印当前libcurl库的版本。
4 CURL *curl_easy_init( );
描述:
curl_easy_init用来初始化一个CURL的指针(有些像返回FILE类型的指针一样). 相应的在调用结束时要用curl_easy_cleanup函数清理.
一般curl_easy_init意味着一个会话的开始. 它的返回值一般都用在easy系列的函数中.
5 void curl_easy_cleanup(CURL *handle);
描述:
这个调用用来结束一个会话.与curl_easy_init配合着用.
参数:
CURL类型的指针.
6 CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter);
描述: 这个函数最重要了.几乎所有的curl 程序都要频繁的使用它.它告诉curl库.程序将有如何的行为. 比如要查看 一个网页的html代码等.(这个函数有些像ioctl函数)参数:
1 CURL类型的指针
2 各种CURLoption类型的选项.(都在curl.h库 里有定义,man 也可 以查看到)
3 parameter 这个参数 既可以是个函数的指针,也可以是某个 对象的指针,也可以是个long型的变量.它用什么这取决于第二个参数.
CURLoption 这个参数的取值很多.具体的可以查看man手册.
7 CURLcode curl_easy_perform(CURL *handle);描述:这个函数在初始化CURL类型的指针 以及curl_easy_setopt完成后调用. 就像字面的意思所说perform就 像是个舞台.让我们设置的
option 运作起来.参数:
CURL类型的指针.
3.3 curl_easy_setopt函数介绍
本节主要介绍curl_easy_setopt中跟http相 关的参数。注意本节的阐述都是以libcurl作为主体,其它为客体来阐述 的。
1. CURLOPT_URL
设置访问URL
2. CURLOPT_WRITEFUNCTION,CURLOPT_WRITEDATA
回调函数原型为:size_t function( void *ptr, size_t size, size_t nmemb, void *stream); 函 数将在libcurl接收到数据后被调用,因此函数多做数据保存的功能,如处理下载文件。CURLOPT_WRITEDATA 用于表明CURLOPT_WRITEFUNCTION函 数中的stream指针的来源。
3. CURLOPT_HEADERFUNCTION,CURLOPT_HEADERDATA
回调函数原型为 size_t function( void *ptr, size_t size,size_t nmemb, void *stream); libcurl一旦接收到http 头部数据后将调用该函数。CURLOPT_WRITEDATA 传递指针给libcurl,该指针表明CURLOPT_HEADERFUNCTION 函数的stream指针的来源。
4. CURLOPT_READFUNCTION CURLOPT_READDATA
libCurl需要读取数据 传递给远程主机时将调用CURLOPT_READFUNCTION指定的函数,函数原型是:size_t function(void *ptr, size_t size, size_t nmemb,void *stream). CURLOPT_READDATA 表明CURLOPT_READFUNCTION函数原型中的stream指针来源。
5. CURLOPT_NOPROGRESS,CURLOPT_PROGRESSFUNCTION,CURLOPT_PROGRESSDATA
跟数据传输进度相关的参数。CURLOPT_PROGRESSFUNCTION 指定的函数正常情况下每秒被libcurl调用一次,为了使CURLOPT_PROGRESSFUNCTION被调用,CURLOPT_NOPROGRESS必须 被设置为false,CURLOPT_PROGRESSDATA指 定的参数将作为CURLOPT_PROGRESSFUNCTION指定函数的第一个参数
6. CURLOPT_TIMEOUT,CURLOPT_CONNECTIONTIMEOUT:
CURLOPT_TIMEOUT 由于设置传输时间,CURLOPT_CONNECTIONTIMEOUT 设置连接等待时间
7. CURLOPT_FOLLOWLOCATION
设置重定位URL
CURLOPT_RANGE: CURLOPT_RESUME_FROM:
断点续传相关设置。CURLOPT_RANGE 指定char *参数传递给libcurl,用于指明http域的RANGE头域,例如:
表示头500个字节:bytes=0-499
表示第二个500字节:bytes=500-999
表示最后500个字节:bytes=-500
表示500字节以后的范围:bytes=500-
第一个和最后一个字节:bytes=0-0,-1
同时指定几个范围:bytes=500-600,601-999
CURLOPT_RESUME_FROM 传 递一个long参数给libcurl,指定你希望开始传递的
偏移量。
3.4 curl_easy_perform 函数说明(error 状 态码)
该函数完成curl_easy_setopt指定的所有选项,本节重点介绍curl_easy_perform的返回值。返回0意味一 切ok,非0代表错误发生。主要错误码说明:
1. CURLE_OK
任务完成一切都好
2 CURLE_UNSUPPORTED_PROTOCOL
不支持的协议,由URL的头部指定
3 CURLE_COULDNT_CONNECT
不能连接到remote 主机或者代理
4 CURLE_REMOTE_ACCESS_DENIED
访问被拒绝
5 CURLE_HTTP_RETURNED_ERROR
Http返回错误
6 CURLE_READ_ERROR
读本地文件错误

3.1 获取html网页

 1 #include <stdio.h>
 2 #include <curl/curl.h>
 3 #include <stdlib.h>
 4 int main(int argc, char *argv[])
 5 {
 6     CURL *curl;             //定义CURL类型的指针
 7 CURLcode res;           //定义CURLcode类型的变量,保存返回状态码
 8     if(argc!=2)
 9     {
10         printf("Usage : file <url>;\n");
11         exit(1);
12     }
13
14     curl = curl_easy_init();        //初始化一个CURL类型的指针
15     if(curl!=NULL)
16     {
17         //设置curl选项. 其中CURLOPT_URL是让用户指 定url. argv[1]中存放的命令行传进来的网址
18         curl_easy_setopt(curl, CURLOPT_URL, argv[1]);
19         //调用curl_easy_perform 执行我们的设置.并进行相关的操作. 在这 里只在屏幕上显示出来.
20         res = curl_easy_perform(curl);
21         //清除curl操作.
22         curl_easy_cleanup(curl);
23     }
24     return 0;
25 }

编译gcc  get_http.c  -o get_http lcurl

./ get_http www.baidu.com

3.2 网页下载保存实例

 1 // 采用CURLOPT_WRITEFUNCTION 实现网页下载保存功能
 2 #include <stdio.h>;
 3 #include <stdlib.h>;
 4 #include <unistd.h>;
 5
 6 #include <curl/curl.h>;
 7 #include <curl/types.h>;
 8 #include <curl/easy.h>;
 9
10 FILE *fp;  //定义FILE类型指针
11 //这个函数是为了符合CURLOPT_WRITEFUNCTION而构造的
12 //完成数据保存功能
13 size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream)
14 {
15     int written = fwrite(ptr, size, nmemb, (FILE *)fp);
16     return written;
17 }
18
19 int main(int argc, char *argv[])
20 {
21     CURL *curl;
22
23     curl_global_init(CURL_GLOBAL_ALL);
24     curl=curl_easy_init();
25     curl_easy_setopt(curl, CURLOPT_URL, argv[1]);
26
27     if((fp=fopen(argv[2],"w"))==NULL)
28     {
29         curl_easy_cleanup(curl);
30         exit(1);
31     }
32 ////CURLOPT_WRITEFUNCTION 将后继的动作交给write_data函数处理
33     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
34     curl_easy_perform(curl);
35     curl_easy_cleanup(curl);
36     exit(0);
37 }

编译gcc  save_http.c  -o save_http lcurl

./ save_http www.baidu.com  /tmp/baidu

3.3 进度条实例??显 示文件下载进度

  1 // 采用CURLOPT_NOPROGRESS, CURLOPT_PROGRESSFUNCTION    CURLOPT_PROGRESSDATA 实现文件传输进度提示功能
  2 //函数采用了gtk库,故编译时需指定gtk库
  3 //函数启动专门的线程用于显示gtk 进度条bar
  4 #include <stdio.h>
  5 #include <gtk/gtk.h>
  6 #include <curl/curl.h>
  7 #include <curl/types.h> /* new for v7 */
  8 #include <curl/easy.h> /* new for v7 */
  9
 10 GtkWidget *Bar;
 11 ////这个函数是为了符合CURLOPT_WRITEFUNCTION而构造的
 12 //完成数据保存功能
 13 size_t my_write_func(void *ptr, size_t size, size_t nmemb, FILE *stream)
 14 {
 15   return fwrite(ptr, size, nmemb, stream);
 16 }
 17 //这个函数是为了符合CURLOPT_READFUNCTION而构造的
 18 //数据上传时使用
 19 size_t my_read_func(void *ptr, size_t size, size_t nmemb, FILE *stream)
 20 {
 21   return fread(ptr, size, nmemb, stream);
 22 }
 23 //这个函数是为了符合CURLOPT_PROGRESSFUNCTION而构造的
 24 //显示文件传输进度,t代表文件大小,d代表传 输已经完成部分
 25 int my_progress_func(GtkWidget *bar,
 26                      double t, /* dltotal */
 27                      double d, /* dlnow */
 28                      double ultotal,
 29                      double ulnow)
 30 {
 31 /*  printf("%d / %d (%g %%)\n", d, t, d*100.0/t);*/
 32   gdk_threads_enter();
 33   gtk_progress_set_value(GTK_PROGRESS(bar), d*100.0/t);
 34   gdk_threads_leave();
 35   return 0;
 36 }
 37
 38 void *my_thread(void *ptr)
 39 {
 40   CURL *curl;
 41   CURLcode res;
 42   FILE *outfile;
 43   gchar *url = ptr;
 44
 45   curl = curl_easy_init();
 46   if(curl)
 47   {
 48     outfile = fopen("test.curl", "w");
 49
 50     curl_easy_setopt(curl, CURLOPT_URL, url);
 51     curl_easy_setopt(curl, CURLOPT_WRITEDATA, outfile);
 52     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_write_func);
 53     curl_easy_setopt(curl, CURLOPT_READFUNCTION, my_read_func);
 54     curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
 55     curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, my_progress_func);
 56     curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, Bar);
 57
 58     res = curl_easy_perform(curl);
 59
 60     fclose(outfile);
 61     /* always cleanup */
 62     curl_easy_cleanup(curl);
 63   }
 64
 65   return NULL;
 66 }
 67
 68 int main(int argc, char **argv)
 69 {
 70   GtkWidget *Window, *Frame, *Frame2;
 71   GtkAdjustment *adj;
 72
 73   /* Must initialize libcurl before any threads are started */
 74   curl_global_init(CURL_GLOBAL_ALL);
 75
 76   /* Init thread */
 77   g_thread_init(NULL);
 78
 79   gtk_init(&argc, &argv);
 80   Window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 81   Frame = gtk_frame_new(NULL);
 82   gtk_frame_set_shadow_type(GTK_FRAME(Frame), GTK_SHADOW_OUT);
 83   gtk_container_add(GTK_CONTAINER(Window), Frame);
 84   Frame2 = gtk_frame_new(NULL);
 85   gtk_frame_set_shadow_type(GTK_FRAME(Frame2), GTK_SHADOW_IN);
 86   gtk_container_add(GTK_CONTAINER(Frame), Frame2);
 87   gtk_container_set_border_width(GTK_CONTAINER(Frame2), 5);
 88   adj = (GtkAdjustment*)gtk_adjustment_new(0, 0, 100, 0, 0, 0);
 89   Bar = gtk_progress_bar_new_with_adjustment(adj);
 90   gtk_container_add(GTK_CONTAINER(Frame2), Bar);
 91   gtk_widget_show_all(Window);
 92
 93   if (!g_thread_create(&my_thread, argv[1], FALSE, NULL) != 0)
 94     g_warning("can't create the thread");
 95
 96
 97   gdk_threads_enter();
 98   gtk_main();
 99   gdk_threads_leave();
100   return 0;
101 }

编译export PKG_CONFIG_PATH=/usr/lib/pkgconfig/
gcc progress.c
o progress ` pkg-config --libs cflags gtk+-2..0` -lcurl lgthread-2.0

./ progress  http://software.sky-union.cn/index.asp

3.4 断点续传实例

  1 //采用CURLOPT_RESUME_FROM_LARGE 实现文件断点续传功能
  2 #include <stdlib.h>
  3 #include <stdio.h>
  4 #include <sys/stat.h>
  5
  6 #include <curl/curl.h>
  7 //这个函数为CURLOPT_HEADERFUNCTION参数构造
  8 /* 从http头部获取文件size*/
  9 size_t getcontentlengthfunc(void *ptr, size_t size, size_t nmemb, void *stream) {
 10        int r;
 11        long len = 0;
 12
 13        /* _snscanf() is Win32 specific */
 14        // r = _snscanf(ptr, size * nmemb, "Content-Length: %ld\n", &len);
 15  r = sscanf(ptr, "Content-Length: %ld\n", &len);
 16        if (r) /* Microsoft: we don't read the specs */
 17               *((long *) stream) = len;
 18
 19        return size * nmemb;
 20 }
 21
 22 /* 保存下载文件 */
 23 size_t wirtefunc(void *ptr, size_t size, size_t nmemb, void *stream)
 24 {
 25         return fwrite(ptr, size, nmemb, stream);
 26 }
 27
 28 /*读取上传文件 */
 29 size_t readfunc(void *ptr, size_t size, size_t nmemb, void *stream)
 30 {
 31        FILE *f = stream;
 32        size_t n;
 33
 34        if (ferror(f))
 35               return CURL_READFUNC_ABORT;
 36
 37        n = fread(ptr, size, nmemb, f) * size;
 38
 39        return n;
 40 }
 41
 42 // 下载 或者上传文件函数
 43 int download(CURL *curlhandle, const char * remotepath, const char * localpath,
 44            long timeout, long tries)
 45 {
 46        FILE *f;
 47        curl_off_t local_file_len = -1 ;
 48        long filesize =0 ;
 49
 50        CURLcode r = CURLE_GOT_NOTHING;
 51        int c;
 52   struct stat file_info;
 53   int use_resume = 0;
 54   /* 得到本地文件大小 */
 55   //if(access(localpath,F_OK) ==0)
 56
 57     if(stat(localpath, &file_info) == 0)
 58      {
 59         local_file_len =  file_info.st_size;
 60         use_resume  = 1;
 61       }
 62   //采用追加方式打开文件,便于实现文件断点续传工作
 63        f = fopen(localpath, "ab+");
 64        if (f == NULL) {
 65               perror(NULL);
 66               return 0;
 67        }
 68
 69        //curl_easy_setopt(curlhandle, CURLOPT_UPLOAD, 1L);
 70
 71        curl_easy_setopt(curlhandle, CURLOPT_URL, remotepath);
 72
 73               curl_easy_setopt(curlhandle, CURLOPT_CONNECTTIMEOUT, timeout);  // 设置连接超时,单位秒
 74        //设置http 头部处理函数
 75        curl_easy_setopt(curlhandle, CURLOPT_HEADERFUNCTION, getcontentlengthfunc);
 76        curl_easy_setopt(curlhandle, CURLOPT_HEADERDATA, &filesize);
 77  // 设置文件续传的位置给libcurl
 78        curl_easy_setopt(curlhandle, CURLOPT_RESUME_FROM_LARGE, use_resume?local_file_len:0);
 79
 80        curl_easy_setopt(curlhandle, CURLOPT_WRITEDATA, f);
 81        curl_easy_setopt(curlhandle, CURLOPT_WRITEFUNCTION, wirtefunc);
 82
 83        //curl_easy_setopt(curlhandle, CURLOPT_READFUNCTION, readfunc);
 84        //curl_easy_setopt(curlhandle, CURLOPT_READDATA, f);
 85        curl_easy_setopt(curlhandle, CURLOPT_NOPROGRESS, 1L);
 86        curl_easy_setopt(curlhandle, CURLOPT_VERBOSE, 1L);
 87
 88
 89   r = curl_easy_perform(curlhandle);
 90
 91
 92        fclose(f);
 93
 94        if (r == CURLE_OK)
 95               return 1;
 96        else {
 97               fprintf(stderr, "%s\n", curl_easy_strerror(r));
 98               return 0;
 99        }
100 }
101
102 int main(int c, char **argv) {
103        CURL *curlhandle = NULL;
104
105        curl_global_init(CURL_GLOBAL_ALL);
106        curlhandle = curl_easy_init();
107
108        //download(curlhandle, "ftp://user:pass@host/path/file", "C:\\file", 0, 3);
109   download(curlhandle , "http://software.sky-union.cn/index.asp","/work/index.asp",1,3);
110        curl_easy_cleanup(curlhandle);
111        curl_global_cleanup();
112
113        return 0;
114 }

编译gcc  resume.c  -o resume lcurl

./ resume

3.5 LibCurl调试实例

  1 //采用CURLOPT_DEBUGFUNCTION参数实现libcurl调试功能
  2 #include <stdio.h>
  3 #include <curl/curl.h>
  4
  5 struct data {
  6   char trace_ascii; /* 1 or 0 */
  7 };
  8
  9 static
 10 void dump(const char *text,
 11           FILE *stream, unsigned char *ptr, size_t size,
 12           char nohex)
 13 {
 14   size_t i;
 15   size_t c;
 16
 17   unsigned int width=0x10;
 18
 19   if(nohex)
 20     /* without the hex output, we can fit more on screen */
 21     width = 0x40;
 22
 23   fprintf(stream, "%s, %zd bytes (0x%zx)\n", text, size, size);
 24
 25   for(i=0; i<size; i+= width) {
 26
 27     fprintf(stream, "%04zx: ", i);
 28
 29     if(!nohex) {
 30       /* hex not disabled, show it */
 31       for(c = 0; c < width; c++)
 32         if(i+c < size)
 33           fprintf(stream, "%02x ", ptr[i+c]);
 34         else
 35           fputs("   ", stream);
 36     }
 37
 38     for(c = 0; (c < width) && (i+c < size); c++) {
 39       /* check for 0D0A; if found, skip past and start a new line of output */
 40       if (nohex && (i+c+1 < size) && ptr[i+c]==0x0D && ptr[i+c+1]==0x0A) {
 41         i+=(c+2-width);
 42         break;
 43       }
 44       fprintf(stream, "%c",
 45               (ptr[i+c]>=0x20) && (ptr[i+c]<0x80)?ptr[i+c]:'.');
 46       /* check again for 0D0A, to avoid an extra \n if it's at width */
 47       if (nohex && (i+c+2 < size) && ptr[i+c+1]==0x0D && ptr[i+c+2]==0x0A) {
 48         i+=(c+3-width);
 49         break;
 50       }
 51     }
 52     fputc('\n', stream); /* newline */
 53   }
 54   fflush(stream);
 55 }
 56
 57 static
 58 int my_trace(CURL *handle, curl_infotype type,
 59              char *data, size_t size,
 60              void *userp)
 61 {
 62   struct data *config = (struct data *)userp;
 63   const char *text;
 64   (void)handle; /* prevent compiler warning */
 65
 66   switch (type) {
 67   case CURLINFO_TEXT:
 68     fprintf(stderr, "== Info: %s", data);
 69   default: /* in case a new one is introduced to shock us */
 70     return 0;
 71
 72   case CURLINFO_HEADER_OUT:
 73     text = "=> Send header";
 74     break;
 75   case CURLINFO_DATA_OUT:
 76     text = "=> Send data";
 77     break;
 78   case CURLINFO_SSL_DATA_OUT:
 79     text = "=> Send SSL data";
 80     break;
 81   case CURLINFO_HEADER_IN:
 82     text = "<= Recv header";
 83     break;
 84   case CURLINFO_DATA_IN:
 85     text = "<= Recv data";
 86     break;
 87   case CURLINFO_SSL_DATA_IN:
 88     text = "<= Recv SSL data";
 89     break;
 90   }
 91
 92   dump(text, stderr, (unsigned char *)data, size, config->trace_ascii);
 93   return 0;
 94 }
 95
 96 int main(void)
 97 {
 98   CURL *curl;
 99   CURLcode res;
100   struct data config;
101
102   config.trace_ascii = 1; /* enable ascii tracing */

转载于:https://www.cnblogs.com/jikexianfeng/p/curl.html

2.1 LibCurl编程流程(转)相关推荐

  1. socket网络编程——TCP编程流程及端口号占用问题

    1.TCP编程流程 1.1TCP服务器端客户端及方法介绍 TCP 提供的是面向连接的.可靠的.字节流服务.TCP 的服务器端和客户端编程流程如下: socket()方法是用来创建一个套接字,有了套接字 ...

  2. step5 . day4 网络编程 基于UDP协议的网络编程流程及API

    UDP协议是面向无连接,不可靠的传输协议,编程流程如下; 服务器端: 1. socket(),返回一个文件描述符,用于通信 2. bind(); //得先完成结构体的填充sockaddr_in 3. ...

  3. step5 . day2 网络编程 基于TPC协议的网络编程流程及API

    基于TCP协议的网络编程流程 服务器端: 1) socket(),创建套接字文件,用于连接 2) bind(), 绑定,把socket()函数返回的文件描述符和IP.端口号进行绑定; 3) liste ...

  4. MFC socket网络编程(流程示例)

    MFC socket网络编程(流程示例) 1.TCP流式套接字的编程步骤 在使用之前须链接库函数:工程->设置->Link->输入ws2_32.lib,OK! 服务器端程序: 1.加 ...

  5. 【Computer Organization笔记07】实验课:可编程逻辑器件介绍,硬件编程方法与原则,硬件编程流程

    本次笔记内容: P13 计算机组成原理(13) P14 计算机组成原理(14) 本节课对应幻灯片: 组成原理52 verilogHDL 组成原理53 fpgahardware 本节课内容为" ...

  6. UDP服务器客户端编程流程

    UDP服务器客户端编程流程 UDP编程流程 UDP服务端代码实现 UDP客户端代码实现 UDP服务端客户端代码详解 UDP编程流程 UDP提供的是无连接.不可靠的.数据报服务 UDP是尽最大能力进行传 ...

  7. FT2232H编程流程分析

    FT2232H编程流程分析 前言 正菜 获取当前连接的FTDI设备 获取指定设备的详细信息 确认设备信息后,打开指定设备 复位设备 清空缓存 配置设备 同步MPSSE 点灯测试代码 配置MPSSE J ...

  8. UG模具数控编程流程讲解,建议收藏

    UG模具数控编程流程讲解 首要咱们拿到了一个产品后,先不要急着分模,最重要的一件事便是先检查产品结构,包含拔模,厚度等模塑型问题.当然这些对于一个刚刚从事模具结构规划的人来说,或许是比较艰难的. 由于 ...

  9. TCP服务器客户端编程流程

    TCP服务器客户端编程流程 TCP编程流程 主机字节序列和网络字节序列 套接字地址结构 通用socket地址结构 一般使用会定义一个专用的套接字结构 IP地址转换函数 网络编程接口 TCP服务段代码实 ...

  10. mapreduce编程流程

    Mapreduce的编程流程主要分八个阶段:两个MAP阶段,四个shuffle阶段,两个reduce阶段. Map两个阶段: 1:设置inputformat类,将数据分为key-value对(k1 v ...

最新文章

  1. 缩略图信息提取工具vinetto
  2. Oracle 把游标说透
  3. 从贝泰妮的全域消费者运营,看Quick Audience如何链接产品服务商生态
  4. base64链接转为地址php,php将图片链接转换为base64编码文件流
  5. 管理维护MySQL的SQL语句有哪些_MySQL常用管理SQL语句
  6. Quartz调用大全
  7. 【net】音乐播放器
  8. java怎么控制数据权限_Java权限控制算法
  9. 2 测试方法与理论 - 软件测试
  10. pytest执行时,报report.html错误
  11. 老路教你用得上的商学课_系列笔记
  12. Unity - Projector - 实时[假]阴影
  13. centos6.5 MailScanner+ Spamassassin垃圾邮件过滤器+clamav 杀毒软件
  14. DNX SDK版本 “dnx-clr-win-x86.1.0.0-beta5”无法安装
  15. 海龟画图----python画美队盾牌
  16. 中国剩余定理(孙子定理)
  17. NOI openjudge 1.1 01:Hello, World!
  18. Arbitrum上首个跨链互操应用开启空投计划!
  19. 如何理解泰勒展开式,他有何用途?
  20. 凸规划问题与二阶锥规划

热门文章

  1. vsftpd虚拟用户与匿名用户配合使用
  2. Android 程序调试
  3. Ajax学习笔记-JQuery中的Ajax
  4. win7下声音图标消失的解决办法
  5. 递归+分治+贪心+动态规划
  6. jqGrid Pager、Navigator和自定义按钮(转)
  7. Log4j 2.x使用遇到的问题
  8. Submitting Applications
  9. 阿里终面:优秀的代码都是如何分层的?
  10. 中国IT行业薪资:与销售相比,程序员真得很“穷”