[文章]【HarmonyOS HiSpark AI Camera试用连载 】第四次遇见-基于鸿蒙OS的文件拷贝

阅读量0
0
0


谁?
我!
是你?
是我!
你终于来了!
我终于来了!
你终究是来了?
我终究是来了!
你来干什么!
我来写一个文件拷贝!

本代码使用鸿蒙os实现一个文件拷贝操作。
源码中使用三个线程(可以通过宏定义更改线程数,建议根据你电脑或者虚拟机的核心数来更改,不过测试中使用小文件,线程开得多耶看不到明显的速度变化,拷贝大文件就能看到速度变化明显)。
本源码仿造迅雷的下载文件机制,通过文件指针的偏移来实现多线程操作,可以在同一时间对文件的多个位置进行拷贝操作,理论上拷贝速度可以达到原来的3倍(决定于宏定义中的数值),实际拷贝速度受制于硬盘读写速度,处理器运算能力,处理器核心数,内核调度策略等一系列外部原因。
一句话,能提速。
文件拷贝过程中,为了防止硬盘空间不足,先读取源文件大小,然后建立新文件,在新文件中偏移指针,大小和源文件相同,在末尾写一个占位符,用来建立一个和源文件一样大小的目标文件,防止拷贝出错。
Ok,话不多说,直接上代码。
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <pthread.h>
  4. #include <sys/types.h>
  5. #include <sys/stat.h>
  6. #include <fcntl.h>
  7. #include <unistd.h>

  8. #define THREADNUM 3
  9. #define BUFSIZE 1024

  10. //多线程文件拷贝程序

  11. void *func(void *arg);

  12. pthread_mutex_t mutex;
  13. char *srcfname = NULL;
  14. char *desfname = NULL;
  15. off_t fsize, fpos=0;

  16. int main(int argc, char **argv)
  17. {
  18.         if(argc!=3)
  19.         {
  20.                 printf("error: command + srcfile + desfilen");
  21.                 exit(1);
  22.         }
  23.         pthread_t tid[THREADNUM];
  24.         int i;
  25.         struct stat finfo;
  26.         pthread_mutex_init(&mutex, NULL);
  27.         
  28.         srcfname = argv[1];
  29.         desfname = argv[2];
  30.         printf("srcfname:%s",srcfname);
  31.         printf("desfname:%s",desfname);
  32.         int fds = open(srcfname, O_RDONLY);
  33.         if(fds<0)
  34.         {
  35.                 perror("open()");
  36.                 exit(1);
  37.         }
  38.         int fdd = open(desfname, O_WRONLY | O_CREAT, 0666);
  39.         stat(srcfname, &finfo);//获取源文件详细信息
  40.         fsize = finfo.st_size;
  41.         lseek(fdd, fsize-1, SEEK_SET);//偏移目标文件指针到源文件的大小
  42.         write(fdd, "\0", 1);//写一个字符在末尾占位

  43.         for(i=0;i<THREADNUM;i++)//创建多线程
  44.         {
  45.                 pthread_create(&tid[i], NULL, func, NULL);
  46.         }
  47.         
  48.         for(i=0; i<THREADNUM; i++)//线程收尸
  49.         {
  50.                 pthread_join(tid[i], NULL);
  51.         }

  52.         close(fds);
  53.         close(fdd);
  54.         pthread_mutex_destroy(&mutex);//摧毁互斥量
  55.         exit(0);
  56. }


  57. void *func(void *arg)
  58. {
  59.         int fds, fdd, flag=0, rdcount=0;
  60.         off_t myfpos;
  61.         char buf[BUFSIZE];
  62.         size_t res;
  63.         fds = open(srcfname, O_RDONLY);
  64.         if(fds<0)
  65.         {
  66.                 perror("open()");
  67.                 pthread_exit(NULL);
  68.         }
  69.         fdd = open(desfname, O_WRONLY);

  70.         //拿到各个线程自己该偏移的位置
  71.         pthread_mutex_lock(&mutex);
  72.         myfpos = fpos;
  73.         fpos += (fsize/THREADNUM);
  74.         if((fsize/THREADNUM)*(THREADNUM-1) == myfpos)
  75.                 flag=1;//标记最后一个拿到任务的线程(特殊)
  76.         pthread_mutex_unlock(&mutex);
  77.         
  78.         lseek(fds, myfpos, SEEK_SET);
  79.         lseek(fdd, myfpos, SEEK_SET);//将文件指针偏移到相应的位置(处理自己的那一部分)

  80.         while(1)
  81.         {
  82.                 res = read(fds, buf, BUFSIZE);
  83.                 rdcount+=res;
  84.                 if(res==0) break;

  85.                 write(fdd, buf, res);
  86.                 if(rdcount >= (fsize/THREADNUM))
  87.                 {
  88.                         if(flag==0) break;
  89.                 }
  90.         }
  91.         
  92.         close(fds);
  93.         close(fdd);
  94.         pthread_exit(NULL);
  95. }
复制代码
关于文件修改和文件烧录参考
https://bbs.elecfans.com/jishu_2001813_1_1.html
https://bbs.elecfans.com/jishu_2008062_1_1.html
运行结果
1.png
2.png
注意,该程序在执行过程中提示需要权限,并且在执行的时候需要加上源文件路径和目标文件路径,不写路径将报错并退出。

回帖

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。 侵权投诉
链接复制成功,分享给好友