多线程实现文件拷贝(Linux下C++)


我们应该都用过迅雷这种下载工具吧,迅雷下载工具中运用了多线程下载。多线程文件拷贝是实现多线程下载的基础,下面给出了多线程文件拷贝的实现代码:
  1. //copyfile.cc   
  2. #include <iostream>   
  3. #include <cstring>   
  4. #include <stdio.h>   
  5. #include <sys/types.h>   
  6. #include <sys/stat.h>   
  7. #include <fcntl.h>   
  8. #include <unistd.h>   
  9. #include <pthread.h>   
  10. using namespace std;  
  11.   
  12. /************************************ 
  13.  *使用指定线程实现从文件的拷贝 
  14.  *创建时间:2011.07.28 
  15.  *修改时间:2011.07.29 
  16.  *作者:hahaya 
  17.  ***********************************/  
  18.   
  19. //最大使用的线程数   
  20. const int MAX_THREADS = 5;  
  21.   
  22. typedef struct TAG_INFO  
  23. {  
  24.     char *fromfile;                 //源地址   
  25.     char *tofile;                  //目的地址   
  26.     int num;                      //启动的第i-1个进程   
  27. }info;  
  28.   
  29. //st_size的类型为__off_t   
  30. int get_size(const char *filename)  
  31. {  
  32.     struct stat st;  
  33.     memset(&st, 0, sizeof(st));  
  34.     stat(filename, &st);  
  35.     return st.st_size;  
  36. }  
  37.   
  38. void* threadDL(void *param)  
  39. {  
  40.     info info1 = *((info*)param);  
  41.       
  42.     FILE *fin = fopen(info1.fromfile, "r+");  
  43.     FILE *fout = fopen(info1.tofile, "w+");  
  44.   
  45.     int size = get_size(info1.fromfile);  
  46.     //将文件指针分别设置在每个线程要读和写的位置    
  47.     fseek(fin, size*(info1.num)/MAX_THREADS, SEEK_SET);  
  48.     fseek(fout, size*(info1.num)/MAX_THREADS, SEEK_SET);  
  49.   
  50.     char buff[1024] = {'\0'};  
  51.     int len = 0;  
  52.     int total = 0;  
  53.     while((len = fread(buff, 1, sizeof(buff), fin)) > 0)  
  54.     {  
  55.     fwrite(buff, 1, len, fout);  
  56.     total += len;  
  57.     //如果读入的数据大于文件总大小除线程总数则停止读入,因为每个线程要读或写的数据就等于文件总大小除线程总数   
  58.     //可能会多写入一些数据,下一次写入时会覆盖多写入的数据,所以不用担心   
  59.     if(total > size/MAX_THREADS)  
  60.     {  
  61.         break;  
  62.     }  
  63.     }  
  64.   
  65.     fclose(fin);  
  66.     fclose(fout);  
  67.   
  68. }  
  69.   
  70. int main(int argc, char *argv[])  
  71. {  
  72.     //先创建一个与文件1同样大小的文件   
  73.     creat(argv[2], 0777);  
  74.     truncate(argv[2], get_size(argv[1]));  
  75.   
  76.     pthread_t pid[MAX_THREADS];  
  77.     info info1;  
  78.     //启动指定线程数的线程   
  79.     for(int i = 0; i < MAX_THREADS; i++)  
  80.    {  
  81.         memset(&info1, 0, sizeof(info1));  
  82.     info1.fromfile = argv[1];  
  83.     info1.tofile = argv[2];  
  84.     info1.num = i;  
  85.     pthread_create(&pid[i], NULL, threadDL, (void*)&info1);  
  86.     }  
  87.     //等待线程结束   
  88.     for(int j = 0; j < MAX_THREADS; j++)  
  89.     {  
  90.     //pthread_join不能用在创建进程的for循环中,否则创建第一个进程后会等待第一个进程结束后创建第二个进程   
  91.     pthread_join(pid[j], NULL);  
  92.     }  
  93.   
  94.     cout << "file copy success......" << endl;  
  95.     return 0;  
  96.       
  97. }  

程序运行截图:



复制后的文件是完整的,可以解压,如下图:

相关内容