我們應該都用過迅雷這種下載工具吧,迅雷下載工具中運用了多線程下載。多線程文件拷貝是實現多線程下載的基礎,下面給出了多線程文件拷貝的實現代碼:
- //copyfile.cc
- #include <iostream>
- #include <cstring>
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <pthread.h>
- using namespace std;
-
- /************************************
- *使用指定線程實現從文件的拷貝
- *創建時間:2011.07.28
- *修改時間:2011.07.29
- *作者:hahaya
- ***********************************/
-
- //最大使用的線程數
- const int MAX_THREADS = 5;
-
- typedef struct TAG_INFO
- {
- char *fromfile; //源地址
- char *tofile; //目的地址
- int num; //啟動的第i-1個進程
- }info;
-
- //st_size的類型為__off_t
- int get_size(const char *filename)
- {
- struct stat st;
- memset(&st, 0, sizeof(st));
- stat(filename, &st);
- return st.st_size;
- }
-
- void* threadDL(void *param)
- {
- info info1 = *((info*)param);
-
- FILE *fin = fopen(info1.fromfile, "r+");
- FILE *fout = fopen(info1.tofile, "w+");
-
- int size = get_size(info1.fromfile);
- //將文件指針分別設置在每個線程要讀和寫的位置
- fseek(fin, size*(info1.num)/MAX_THREADS, SEEK_SET);
- fseek(fout, size*(info1.num)/MAX_THREADS, SEEK_SET);
-
- char buff[1024] = {'\0'};
- int len = 0;
- int total = 0;
- while((len = fread(buff, 1, sizeof(buff), fin)) > 0)
- {
- fwrite(buff, 1, len, fout);
- total += len;
- //如果讀入的數據大於文件總大小除線程總數則停止讀入,因為每個線程要讀或寫的數據就等於文件總大小除線程總數
- //可能會多寫入一些數據,下一次寫入時會覆蓋多寫入的數據,所以不用擔心
- if(total > size/MAX_THREADS)
- {
- break;
- }
- }
-
- fclose(fin);
- fclose(fout);
-
- }
-
- int main(int argc, char *argv[])
- {
- //先創建一個與文件1同樣大小的文件
- creat(argv[2], 0777);
- truncate(argv[2], get_size(argv[1]));
-
- pthread_t pid[MAX_THREADS];
- info info1;
- //啟動指定線程數的線程
- for(int i = 0; i < MAX_THREADS; i++)
- {
- memset(&info1, 0, sizeof(info1));
- info1.fromfile = argv[1];
- info1.tofile = argv[2];
- info1.num = i;
- pthread_create(&pid[i], NULL, threadDL, (void*)&info1);
- }
- //等待線程結束
- for(int j = 0; j < MAX_THREADS; j++)
- {
- //pthread_join不能用在創建進程的for循環中,否則創建第一個進程後會等待第一個進程結束後創建第二個進程
- pthread_join(pid[j], NULL);
- }
-
- cout << "file copy success......" << endl;
- return 0;
-
- }
程序運行截圖:
復制後的文件是完整的,可以解壓,如下圖: