在系统文件IO与标准文件IO实现复制文件指令

一、系统文件IO

1.利用分块

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

#define BUFF_SIZE 64

int main(int argc,char* argv[])
{
    if(argc != 3)
    {
        printf("错误参数!\n");
        return -1;
    }
    int input_fd = open(argv[1],O_RDONLY);
    if(input_fd == -1)
    {
        perror("error");
    }
    int output_fd = open(argv[2],O_WRONLY|O_CREAT);
    if(output_fd == -1)
    {
        perror("error");
    }
    int pos_end = lseek(input_fd,0,SEEK_END);
    int pos_start = lseek(input_fd,0,SEEK_SET);
    int len = pos_end-pos_start;
    printf("%d\n",len);
    char buff[BUFF_SIZE];
    int count = len%BUFF_SIZE;
    int loop = len/BUFF_SIZE;
    int read_num = 0;
    if(count == 0)
    {
        
    }
    else
    {
        loop++;
    }
    for(int i = 0;i<loop;i++)
    {
        memset(buff,0,sizeof(buff));
        read_num = read(input_fd,buff,sizeof(buff));
        write(output_fd,buff,read_num); 
    }
}

2.利用双进程

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <errno.h>

#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>

int main(int argc,char* argv[])
{
    if(argc != 3)
    {
        printf("输入格式:%s <src> <dst>\n",argv[0]);
        exit(1);
    }
    //创建一个子线程
    pid_t a = fork();

    //父子进程都打开源文件和目标文件
    int fd1 = open(argv[1],O_RDONLY);
    int fd2 = open(argv[2],O_CREAT|O_RDWR|O_TRUNC,0644);
    if(fd1 == -1 || fd2 == -1)
    {
        perror("error");
        exit(1);
    }

    int size = lseek(fd1,0,SEEK_END);//获取文件的大小
    if(a == 0)//在子线程中,将位置偏移量调整到中间位置(形成空洞)
    {
        lseek(fd1,size/2,SEEK_SET);
        lseek(fd2,size/2,SEEK_SET);
    }
    else if(a>0)//在父进程中,将位置偏移量是调整到文件开头处
    {
        lseek(fd1,0,SEEK_SET);
    }
    char buf[100];
    int nread;
    while(1)
    {
        bzero(buf,100);
        nread = read(fd1,buf,100);
        if(nread == 0)
        {
            break;
        }
        if(a>0)
        {
            //在父进程中,查看当前偏移量是否已经到达中间位置
            int n;
            n = lseek(fd1,0,SEEK_CUR)-size/2;
            if(n>=0)
            {
                //父进程从超过一半的地方开始写
                write(fd2,buf,n);//写入未超过中间位置的字节
                exit(0);//然后退出
            }
        }
        //子进程在一半以前的地方写
        write(fd2,buf,nread);
    }
    close(fd1);
    close(fd2);

    return 0;

 

二、标准文件IO

1.利用分块

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
./02 /home/harold/C_Linux/04day/work/02_input.txt /home/harold/C_Linux/04day/work/02_output.txt
*/
#define BUFF_SIZE 128
int main(int argc,char* argv[])
{
    if(argc != 3)
    {
        printf("输入格式:%s <src> <dst>\n",argv[0]);
        exit(1);
    }
    FILE* fd_input = fopen(argv[1],"r");
    FILE* fd_output = fopen(argv[2],"w");
    if(fd_input == NULL|| fd_output == NULL)
    {
        perror("error");
        exit(1);
    }
    char buff[BUFF_SIZE+1] = {0};
    while(!feof(fd_input))
    {
        fread(buff,BUFF_SIZE,1,fd_input);
        fwrite(buff,strlen(buff),1,fd_output);
        __bzero(buff,sizeof(buff));
    }
    fclose(fd_input);
    fclose(fd_output);

}

2.利用双进程

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

#define BUFF_SIZE 128

int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        fprintf(stderr, "Usage: %s <src> <dst>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    // 打开输入文件
    FILE *input = fopen(argv[1], "rb");
    if (!input)
    {
        perror("fopen input failed");
        exit(EXIT_FAILURE);
    }

    // 获取文件大小
    fseek(input, 0, SEEK_END);
    long file_size = ftell(input);
    rewind(input);

    // 预创建输出文件
    int fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if (fd == -1)
    {
        perror("open output failed");
        exit(EXIT_FAILURE);
    }
    if (ftruncate(fd, file_size) == -1)
    {
        perror("ftruncate failed");
        exit(EXIT_FAILURE);
    }
    close(fd);

    pid_t pid = fork();
    if (pid < 0)
    {
        perror("fork failed");
        exit(EXIT_FAILURE);
    }

    // 各自独立打开输出文件
    FILE *output = fopen(argv[2], "r+b");
    if (!output)
    {
        perror("fopen output failed");
        exit(EXIT_FAILURE);
    }

    if (pid == 0)
    { // 子进程处理后半部分
        fseek(input, file_size / 2, SEEK_SET);
        fseek(output, file_size / 2, SEEK_SET);

        char buffer[BUFF_SIZE];
        size_t total = 0;
        size_t max_read = file_size - file_size / 2;

        while (total < max_read)
        {
            size_t to_read = (max_read - total) > sizeof(buffer) ? sizeof(buffer) : (max_read - total);
            size_t nread = fread(buffer, 1, to_read, input);
            if (nread == 0)
                break;

            size_t nwritten = fwrite(buffer, 1, nread, output);
            if (nwritten != nread)
            {
                perror("Child write failed");
                exit(EXIT_FAILURE);
            }
            total += nwritten;
        }
    }
    else
    { // 父进程处理前半部分
        fseek(output, 0, SEEK_SET);

        char buffer[BUFF_SIZE];
        size_t total = 0;
        size_t target = file_size / 2;

        while (total < target)
        {
            size_t to_read = (target - total) > sizeof(buffer) ? sizeof(buffer) : (target - total);
            size_t nread = fread(buffer, 1, to_read, input);
            if (nread == 0)
                break;

            size_t nwritten = fwrite(buffer, 1, nread, output);
            if (nwritten != nread)
            {
                perror("Parent write failed");
                exit(EXIT_FAILURE);
            }
            total += nwritten;
        }
    }

    fclose(input);
    fclose(output);
    return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define BUFF_SIZE 4096

int main(int argc, char* argv[]) {
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <src> <dst>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    // 打开输入文件
    FILE* input = fopen(argv[1], "r");
    if (!input) {
        perror("Input file open failed");
        exit(EXIT_FAILURE);
    }

    // 获取文件大小
    fseek(input, 0, SEEK_END);
    long file_size = ftell(input);
    rewind(input);

    // 创建并初始化输出文件
    FILE* output = fopen(argv[2], "w");  // 使用读写模式创建文件
    if (!output) {
        perror("Output file create failed");
        exit(EXIT_FAILURE);
    }

    // 预分配空间(标准I/O方式)
    fseek(output, file_size-1, SEEK_SET);
    fputc('\0', output);
    rewind(output);

    pid_t pid = fork();
    if (pid < 0) {
        perror("Fork failed");
        exit(EXIT_FAILURE);
    }

    if (pid == 0) { // 子进程处理后半部分
        fseek(input, file_size/2, SEEK_SET);
        fseek(output, file_size/2, SEEK_SET);

        unsigned char buffer[BUFF_SIZE];
        size_t remaining = file_size - file_size/2;

        while (remaining > 0) {
            size_t chunk = remaining > sizeof(buffer) ? sizeof(buffer) : remaining;
            size_t nread = fread(buffer, 1, chunk, input);
            if (nread == 0) break;

            size_t nwritten = fwrite(buffer, 1, nread, output);
            if (nwritten != nread) {
                perror("Child write error");
                exit(EXIT_FAILURE);
            }
            remaining -= nwritten;
        }
    } else { // 父进程处理前半部分
        unsigned char buffer[BUFF_SIZE];
        size_t remaining = file_size/2;

        while (remaining > 0) {
            size_t chunk = remaining > sizeof(buffer) ? sizeof(buffer) : remaining;
            size_t nread = fread(buffer, 1, chunk, input);
            if (nread == 0) break;

            size_t nwritten = fwrite(buffer, 1, nread, output);
            if (nwritten != nread) {
                perror("Parent write error");
                exit(EXIT_FAILURE);
            }
            remaining -= nwritten;
        }
    }

    // 确保所有缓冲数据写入磁盘
    fflush(output);
    fsync(fileno(output));

    fclose(input);
    fclose(output);
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值