使用一种功能复制文本和二进制文件?

标签 c file-io

我有两个功能。一种复制文本文件,使用"r""w" 模式进行读写,另一种复制二进制文件,使用"rb""wb"模式。

但是如果我要使用这些功能,我必须首先确定我要复制的文件是文本文件还是二进制文件。我想要一个解决方案,允许我在不知道文件性质的情况下成功复制文件。处理这个问题的单个函数。有任何想法吗?

P.S:我注意到 ctrl + c copy 比我的函数更快,因此也欢迎提供提高函数速度的提示。

#include <stdio.h>

void copyfile_txt(const char *inputfile, const char *outputfile);
void copyfile_bin(const char *inputfile, const char *outputfile);

int main(void)
{
    copyfile_txt("file_input.txt", "file_output.txt");
    copyfile_bin("ubuntu-14.04.3-desktop-amd64.iso", "Ubuntu.iso");
    return 0;
}

long GetFileSize(FILE *fp)
{
    fseek(fp, 0L, SEEK_END);
    long sz = ftell(fp);
    fseek(fp, 0L, SEEK_SET);
    return sz;
}
void copyfile_txt(const char *inputfile, const char *outputfile)
{
    static FILE *fp_I;
    static FILE *fp_O;

    fp_I = fopen(inputfile, "r");
    if (!fp_I) {
        perror(inputfile);
        return;
    }

    fp_O = fopen(outputfile, "w");
    if (!fp_O) {
        fclose(fp_I);
        perror(outputfile);
        return;
    }

    static int c;
    while ((c = getc(fp_I)) != EOF) {
        putc(c, fp_O);
    }
    fclose(fp_I);
    fclose(fp_O);
}
void copyfile_bin(const char *inputfile, const char *outputfile)
{
    static FILE *fp_I;
    static FILE *fp_O;

    fp_I = fopen(inputfile, "rb");
    if (!fp_I) {
        perror(inputfile);
        return;
    }

    fp_O = fopen(outputfile, "wb");
    if (!fp_O) {
        fclose(fp_I);
        perror(outputfile);
        return;
    }

    static int c;
    static long n;
    static long sz;

    n = 0;
    sz = GetFileSize(fp_I);

    while (n++ < sz) {
        c = getc(fp_I);
        putc(c, fp_O);
    }

    fclose(fp_I);
    fclose(fp_O);
}

最佳答案

您不需要对文本文件进行特例,将所有文件复制为二进制文件。这是大多数文件复制实用程序所做的。

但是请注意,您的二进制文件复制功能有问题:

  • 无需计算文件大小,复制直到得到 EOF 是正确的,并且允许您复制大于 LONG_MAX 的文件。

  • 不需要静态变量:使用 static 变量会使您的函数在多个线程中使用时失败。

  • 返回完成代码会很有用。

这是一个更简单的版本:

int copyfile_bin(const char *inputfile, const char *outputfile) {
    FILE *fp_I;
    FILE *fp_O;

    fp_I = fopen(inputfile, "rb");
    if (!fp_I) {
        perror(inputfile);
        return -1;
    }

    fp_O = fopen(outputfile, "wb");
    if (!fp_O) {
        fclose(fp_I);
        perror(outputfile);
        return -1;
    }

    int c;
    while ((c = getc(fp_I)) != EOF) {
        putc(c, fp_O);
    }

    fclose(fp_I);
    if (fclose(fp_O) != 0) {
        perror(outputfile);
        return -1;
    }
    return 0;
}

为了提高速度,您可以使用 setvbuf() 或使用 fread()fwrite() 来增加缓冲区大小分配缓冲区。

为了更快的内部循环,使用这个:

    size_t nr, size = 1024 * 1024;
    void *buffer = malloc(size);
    if (buffer != NULL) {
        while ((nr = fread(buffer, 1, size, fp_I)) > 0) {
            if (fwrite(buffer, 1, nr, fp_O) != nr) {
                fprintf(stderr, "write error: ");
                perror(outputfile);
                free(buffer);
                fclose(fp_I);
                fclose(fp_O);
                return -1;
            }
        }
        if (ferror(fp_I)) {
            fprintf(stderr, "read error: ");
            perror(inputfile);
            free(buffer);
            fclose(fp_I);
            fclose(fp_O);
            return -1;
        }
        free(buffer);
    } else {
        /* use the regular getc/putc loop */
        int c;
        while ((c = getc(fp_I)) != EOF) {
            putc(c, fp_O);
        }
    }

关于使用一种功能复制文本和二进制文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39191266/

相关文章:

c++ - 这个条件检查语句在 for 循环中合法吗?

hell C代码: quick sort program running to infinite loop : weird situation

java - 读取文本文件时检查不可打印字符的行

c - 我如何忽略 C 中每行某个位置之后的字符?

windows - 回显到文件时 Ant 不会创建 NL

c - 如何修改背包 - 找到最大加权和

c - 接收所有套接字(直到消息结束符号),C

c - 如何将参数传递给使用 libevent 创建的事件函数?

javascript - 如何在没有提示的情况下在 Google Chrome App 中写入文件?

Python文件读取问题