|
【HarmonyOS HiSpark AI Camera试用连载 】第四次遇见-基于鸿蒙OS的文件拷贝, 谁? 我! 是你? 是我! 你终于来了! 我终于来了! 你终究是来了? 我终究是来了! 你来干什么! 我来写多一个文件拷贝!
本代码使用鸿蒙OS实现一个文件拷贝操作。 源码中使用三个线程(可以通过宏定义更改线程数,建议根据你电脑或者虚拟机的核心数来更改,不过测试中使用小文件,线程开得多耶看不到明显是速度变化,拷贝大文件就能看到速度变化吗明显)。 本源码仿造迅雷的下载文件机制,通过文件指针的偏移来实现多线程操作,可以在同一时间对文件的多个位置进行拷贝操作,理论上拷贝速度可以达到原来的3倍(决定于宏定义中的数值),实际拷贝速度受制于硬盘读写速度,处理器运算能力,处理器核心数,内核调度策略等一系列外部原因。 一句话,能提速。 文件拷贝过程中,为了防止硬盘空间不足,先读取源文件大小,然后建立新文件,在新文件中偏移指针,大小和源文件相同,在末尾写一个占位符,用来建立一个和源文件一样大小的目标文件,防止拷贝出错。 Ok,话不多说,直接上代码。
- #include <stdio.h>
- #include <stdlib.h>
- #include <pthread.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
- #define THREADNUM 3
- #define BUFSIZE 1024
- //多线程文件拷贝程序
- void *func(void *arg);
- pthread_mutex_t mutex;
- char *srcfname = NULL;
- char *desfname = NULL;
- off_t fsize, fpos=0;
- int main(int argc, char **argv)
- {
- if(argc!=3)
- {
- printf(“error: command + srcfile + desfile\n“);
- exit(1);
- }
- pthread_t tid[THREADNUM];
- int i;
- struct stat finfo;
- pthread_mutex_init(&mutex, NULL);
-
- srcfname = argv[1];
- desfname = argv[2];
- printf(“srcfname:%s“,srcfname);
- printf(“desfname:%s“,desfname);
- int fds = open(srcfname, O_RDONLY);
- if(fds<0)
- {
- perror(“open()“);
- exit(1);
- }
- int fdd = open(desfname, O_WRONLY | O_CREAT, 0666);
- stat(srcfname, &finfo);//获取源文件详细信息
- fsize = finfo.st_size;
- lseek(fdd, fsize-1, SEEK_SET);//偏移目标文件指针到源文件的大小
- write(fdd, “\0“, 1);//写一个字符在末尾占位
- for(i=0;i<THREADNUM;i++)//创建多线程
- {
- pthread_create(&tid, NULL, func, NULL);
- }
-
- for(i=0; i<THREADNUM; i++)//线程收尸
- {
- pthread_join(tid, NULL);
- }
- close(fds);
- close(fdd);
- pthread_mutex_destroy(&mutex);//摧毁互斥量
- exit(0);
- }
- void *func(void *arg)
- {
- int fds, fdd, flag=0, rdcount=0;
- off_t myfpos;
- char buf[BUFSIZE];
- size_t res;
- fds = open(srcfname, O_RDONLY);
- if(fds<0)
- {
- perror(“open()“);
- pthread_exit(NULL);
- }
- fdd = open(desfname, O_WRONLY);
- //拿到各个线程自己该偏移的位置
- pthread_mutex_lock(&mutex);
- myfpos = fpos;
- fpos += (fsize/THREADNUM);
- if((fsize/THREADNUM)*(THREADNUM-1) == myfpos)
- flag=1;//标记最后一个拿到任务的线程(特殊)
- pthread_mutex_unlock(&mutex);
-
- lseek(fds, myfpos, SEEK_SET);
- lseek(fdd, myfpos, SEEK_SET);//将文件指针偏移到相应的位置(处理自己的那一部分)
- while(1)
- {
- res = read(fds, buf, BUFSIZE);
- rdcount+=res;
- if(res==0) break;
- write(fdd, buf, res);
- if(rdcount >= (fsize/THREADNUM))
- {
- if(flag==0) break;
- }
- }
-
- close(fds);
- close(fdd);
- pthread_exit(NULL);
- }
-
复制代码 关于文件修改和文件烧录参考 https://bbs.elecfans.com/jishu_2001813_1_1.html <span] https://bbs.elecfans.com/jishu_2008062_1_1.html 运行结果 <span]
1.png (1.98 KB, 下载次数: 0)
下载附件 保存到相册
10 分钟前 上传
2.png (9.57 KB, 下载次数: 0)
下载附件 保存到相册
10 分钟前 上传 注意,该程序在执行过程中提示需要权限,并且在执行的时候需要加上源文件路径和目标文件路径,不写路径将报错并退出。 |
|