现在的位置: 首页 > 综合 > 正文

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

2013年10月09日 ⁄ 综合 ⁄ 共 1690字 ⁄ 字号 评论关闭

    我们应该都用过迅雷这种下载工具吧,迅雷下载工具中运用了多线程下载。多线程文件拷贝是实现多线程下载的基础,下面给出了多线程文件拷贝的实现代码:

//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;
    
}

程序运行截图:

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

抱歉!评论已关闭.