C 程序多线程拆分文件

打印 上一主题 下一主题

主题 1011|帖子 1011|积分 3033

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
C 程序多线程拆分文件

在C语言中,实现多线程来拆分文件通常必要借助多线程库,比如 POSIX 线程库(pthread)或者 Windows 的线程库(CreateThread 或类似的函数)。下面我将分别展示在 Linux 和 Windows 环境下使用这两种方式拆分文件的示例。



在 Linux 下使用 pthread

起首,确保你的系统支持 POSIX 线程
  1. #include <pthread.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <unistd.h>
  5. /*  定义线程的工作函数    */
  6. void* split_file(void* arg) {
  7.     int thread_id = *((int*)arg);
  8.     FILE* src = fopen("source.txt", "rb");
  9.     if (!src) {
  10.         perror("Failed to open source file");
  11.         return NULL;
  12.     }
  13.    
  14.     fseek(src, 0, SEEK_END);
  15.     long filesize = ftell(src);
  16.     fseek(src, 0, SEEK_SET);
  17.    
  18.     long part_size = filesize / 2; // 简单分割为两半
  19.     long start_pos = thread_id * part_size;
  20.     long end_pos = (thread_id + 1) * part_size;
  21.     if (thread_id == 1) end_pos = filesize; // 确保第二个部分读取剩余部分
  22.    
  23.     char filename[50];
  24.     sprintf(filename, "part%d.txt", thread_id + 1);
  25.     FILE* dest = fopen(filename, "wb");
  26.     if (!dest) {
  27.         perror("Failed to open destination file");
  28.         fclose(src);
  29.         return NULL;
  30.     }
  31.    
  32.     fseek(src, start_pos, SEEK_SET);
  33.     char buffer[1024];
  34.     while (ftell(src) < end_pos) {
  35.         size_t bytes_read = fread(buffer, 1, sizeof(buffer), src);
  36.         fwrite(buffer, 1, bytes_read, dest);
  37.     }
  38.    
  39.     fclose(src);
  40.     fclose(dest);
  41.     return NULL;
  42. }
  43. /*   主函数中创建和管理线程  */
  44. int main() {
  45.     pthread_t threads[2];
  46.     int thread_ids[2] = {0, 1}; // 两个线程,分别处理文件的前半部和后半部
  47.    
  48.     for (int i = 0; i < 2; i++) {
  49.         if (pthread_create(&threads[i], NULL, split_file, &thread_ids[i])) {
  50.             fprintf(stderr, "Error creating thread\n");
  51.             return 1;
  52.         }
  53.     }
  54.    
  55.     for (int i = 0; i < 2; i++) {
  56.         pthread_join(threads[i], NULL);
  57.     }
  58.    
  59.     printf("File split successfully.\n");
  60.     return 0;
  61. }
复制代码
在 Windows下使用 CreateThread

在Windows环境下,使用CreateThread函数来实现多线程拆分文件是一种常见的方法。CreateThread函数是Windows API的一部分,用于创建一个新的线程。下面,我将具体介绍如何使用CreateThread来实现一个简单的文件拆分程序。
  1. #include <windows.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. /*   定义线程函数   */
  5. DWORD WINAPI SplitFile(LPVOID lpParam) {
  6.     // 定义结构体传递参数
  7.     struct ThreadParams {
  8.         const char* inputFilePath;
  9.         const char* outputFilePath;
  10.         long startPos;
  11.         long length;
  12.     };
  13.     // 类型转换参数
  14.     ThreadParams* params = (ThreadParams*)lpParam;
  15.     // 打开输入文件和输出文件
  16.     FILE* inputFile = fopen(params->inputFilePath, "rb");
  17.     FILE* outputFile = fopen(params->outputFilePath, "wb");
  18.     if (inputFile == NULL || outputFile == NULL) {
  19.         printf("Error opening file\n");
  20.         return -1;
  21.     }
  22.     // 移动到开始位置并读取数据
  23.     fseek(inputFile, params->startPos, SEEK_SET);
  24.     char buffer[1024]; // 定义缓冲区大小
  25.     long bytesRead;
  26.     for (long pos = params->startPos; pos < params->startPos + params->length; pos += bytesRead) {
  27.         bytesRead = fread(buffer, 1, sizeof(buffer), inputFile);
  28.         if (bytesRead > 0) {
  29.             fwrite(buffer, 1, bytesRead, outputFile);
  30.         } else {
  31.             break; // 文件结束或出错时退出循环
  32.         }
  33.     }
  34.     // 关闭文件
  35.     fclose(inputFile);
  36.     fclose(outputFile);
  37.     return 0;
  38. }
  39. /* 主函数中创建线程并传递参数
  40. 在主函数中,你需要创建多个线程,每个线程处理文件的一部分。你需要计算每个线程应该处理的起始位置和长度  **/
  41. int main() {
  42.     const char* inputFilePath = "largefile.dat";  // 大文件路径
  43.     long fileSize; // 文件大小,单位:字节
  44.     FILE* file = fopen(inputFilePath, "rb");
  45.     if (file == NULL) {
  46.         printf("Error opening file\n");
  47.         return -1;
  48.     }
  49.     fseek(file, 0, SEEK_END); // 移动到文件末尾以获取大小
  50.     fileSize = ftell(file);   // 获取文件大小(字节)
  51.     fclose(file);            // 关闭文件句柄,因为不再需要它读取文件大小了
  52.     int numThreads = 4; // 使用4个线程进行拆分,可根据需要调整数量
  53.     long partSize = fileSize / numThreads; // 每部分的大小(字节)
  54.     HANDLE threads[numThreads]; // 线程句柄数组
  55.     struct ThreadParams params[numThreads]; // 参数数组
  56.   
  57.     for (int i = 0; i < numThreads; i++) {
  58.         params[i].inputFilePath = inputFilePath;
  59.         params[i].outputFilePath = malloc(256); // 为每个输出文件分配路径字符串空间(例如:part1.dat, part2.dat等)
  60.         sprintf(params[i].outputFilePath, "part%d.dat", i + 1); // 设置输出文件名
  61.         params[i].startPos = i * partSize; // 计算开始位置
  62.         params[i].length = (i == numThreads - 1) ? fileSize - params[i].startPos : partSize; // 最后一部分可能需要调整长度以覆盖剩余部分
  63.         threads[i] = CreateThread(NULL, 0, SplitFile, &params[i], 0, NULL); // 创建线程并传递参数
  64.     }
  65.   
  66.     // 等待所有线程完成
  67.     WaitForMultipleObjects(numThreads, threads, TRUE, INFINITE); // 等待所有线程完成执行。TRUE表示等待所有对象。INFINITE表示无限等待。
  68.   
  69.     // 清理资源(关闭句柄)和释放分配的内存空间等操作。这里省略具体实现,实际应用中需要
  70. }
复制代码
附件一:多线程上风

线程程序作为一种多任务、并发的工作方式,当然有其存在上风:
进步应用程序响应:
这对图形界面的程序尤其有意义,当一个操作耗时很长时,整个系统都会等待这个操作,此时程序不会响应键盘、鼠标、菜单的操作,而使用多线程技能,将耗时长的操作(time consuming)置于一个新的线程,可以避免这种尴尬的环境。
使多CPU系统更加有效:
操作系统会包管当线程数不大于CPU数目时,不同的线程运行于不同的CPU上。
改善程序结构:
一个既长又复杂的进程可以考虑分为多个线程,成为几个独立或半独立的运行部分,这样的程序会利于理解和修改。

附件二:操作步骤

线程创建
函数原型:int pthread_create(pthread_t*restrict tidp,const pthread_attr_t *restrict attr,void *(*start_rtn)(void),void *restrict arg);
返回值:如果成功建立线程返回0,否则返回错误的编号。
情势参数:pthread_t*restrict tidp要创建的线程的线程id指针;const pthread_attr_t *restrict attr创建线程时的线程属性;void *(start_rtn)(void)返回值是void类型的指针函数;void *restrict arg start_rtn的形参。
线程挂起:该函数的作用使恰当火线程挂起,等待另一个线程返回才继承执行。也就是说当程序运行到这个地方时,程序会先停止,然后等线程id为thread的这个线程返回,然后程序才会断续执行。
函数原型:intpthread_join(pthread_tthread, void **value_ptr);
参数说明如下:thread等待退出线程的线程号;value_ptr退出线程的返回值。
返回值:若成功,则返回0;若失败,则返回错误号。
线程退出
函数原型:voidpthread_exit(void *rval_ptr);
获取当火线程id
函数原型:pthread_t pthread_self(void);
互斥锁
创建pthread_mutex_init;销毁pthread_mutex_destroy;加锁pthread_mutex_lock;解锁pthread_mutex_unlock。
条件锁
创建pthread_cond_init;销毁pthread_cond_destroy;触发pthread_cond_signal;广播pthread_cond_broadcast;等待pthread_cond_wait。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

怀念夏天

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表