【问题标题】:Merging two files into a third in C (fread and fwrite)在 C 中将两个文件合并为第三个文件(fread 和 fwrite)
【发布时间】:2023-07-30 15:35:01
【问题描述】:

我正在尝试创建一个函数,该函数接受一系列文件并将每个文件的内容写入一个新文件。

#include <stdio.h>
#include <stdlib.h>

    void file_copy(FILE *f1, FILE *f2) {
    char buffer[BUFFER_SIZE];
    size_t sz;
    sz = fread(buffer, sizeof(buffer),1,f1);
    while (sz == 1) {
        fwrite(buffer, sz,1,f2);
        sz = fread(buffer, sizeof(buffer),1,f1);
    }
}

int main(int argc, char const *argv[])
{
    FILE *f_in, *f_out;
    int i;
    if (argc < 3)
    {
        puts("Not enough arguments.");
        exit(1);
    }

    if ((f_out = fopen(argv[argc-1], "w")) == NULL)
    {
        printf("Can't open %s for writing.\n", argv[argc-1]);
        exit(1);
    }

    for (i = 0; i < argc-1; ++i)
    {
        if ((f_in = fopen(*++argv, "r")) == NULL)
        {
            printf("Can't open %s for reading\n", *argv);
            exit(1);
        }
        else
            file_copy(f_in, f_out);
        close(f_in);
        close(f_out);
    }


    return 0;
}

我没有在我的输出文件中得到任何输出。 它似乎正在正确地关闭它们。

【问题讨论】:

  • 我认为您对fread() 返回的内容有误解。它返回读取的项目数。在您的声明中,大小为 1024,因此期望返回 1 意味着读取了 1024 个字节或 0 读取了少于 1024 个字节。如果您交换了大小和计数,那么fread() 返回的值将与您的预期一致。这意味着如果您尝试读取 1024 个大小为 1 字节的项目,则该值将返回读取的字节数。
  • 我改了功能还是不行。
  • 您修复了该功能,但其他所有功能仍然损坏。
  • fopen()打开文件时,需要用fclose()关闭,而不是close()close()需要声明:#include &lt;unistd.h&gt;

标签: c fwrite fread


【解决方案1】:

您是否打算将文件列表中的文本保存到最后一个文件中?这还不是很清楚。 除了不可读的语法之外,代码还存在多个问题。您应该使用fclose 而不是close。并读取多个单字节元素,而不是巨型数组的一个元素。

这里是固定代码:

#include <stdio.h>
#include <stdlib.h>

void file_copy(FILE *f1, FILE *f2) {
    char buffer[1024];
    ssize_t sz;

    while (!feof(f1)) {
        sz = fread(buffer, 1, sizeof(buffer), f1);

        fwrite(buffer, 1, sz, f2);
    }
}

int main(int argc, char const *argv[])
{
    FILE *f_in, *f_out;
    int i;
    if (argc < 3)
    {
        puts("Not enough arguments.");
        exit(1);
    }

    if ((f_out = fopen(argv[argc-1], "w")) == NULL)
    {
        printf("Can't open %s for writing.\n", argv[argc-1]);
        exit(1);
    }

    for (i = 1; i < argc-1; i++)
    {
        if ((f_in = fopen(argv[i], "r")) == NULL)
        {
            printf("Can't open %s for reading\n", *argv);
            exit(1);
        }
        else
        {
            file_copy(f_in, f_out);
            fclose(f_in);
        }
    }
    fclose(f_out);

    return 0;
}

【讨论】:

【解决方案2】:

有几个失败:

  1. 必须以某种方式分配缓冲区
  2. write 必须写入读取的字节数,而不是完整的缓冲区

所以应该是这样的:

#define BUF_SIZE 1024

void file_copy(FILE *f1, FILE *f2) {
    char buffer[BUF_SIZE];

    while (!feof(f1)) {
        size_t r = fread(buffer, 1, sizeof(buffer), f1);
        fwrite(buffer, 1, r, f2);
    }
}

【讨论】:

  • 我试过了,现在文件上没有写任何东西。
  • 可能你在这个函数之外还有其他错误。可能没有关闭文件。
  • 我在那里发布了我的完整代码,我认为这不是问题。
  • 当然,您必须将close(f_out) 移出for 循环。
  • @Telefang - 你们都错了。 fread()fwrite() 的第二个参数告诉缓冲区的大小,而第三个参数告诉要读取或写入这些大小中的多少。如果您的文件小于 1024 字节,则 r 的值将为 0。如果文件大于 1024 字节,则每次读取的 r 的值将为 1。简而言之,您正在读取 1 个 1024 字节计数每次通话。成功读取 1024 字节时返回 1,否则 ii 读取小于 1024 字节时返回 0。
【解决方案3】:

您绝对应该知道要写多少,因为无论如何您最终都会写 1024 个字节,就像现在一样。

根据您处理的文件类型,这至少是 txt 文件的一个选项:

void file_copy(FILE *f1, FILE *f2) {

    fseek(f1, 0, SEEK_END);
    int buf_size = ftell(f1);
    char buf[buf_size];

    //Reset file position
    fseek(f1, 0, SEEK_SET);
    sz = fread(buf, sizeof(buf), 1, f1);
    fwrite(buf, sz, 1, f2);
}

【讨论】:

  • 当您尝试复制 DVD iso 文件时,这会失败。缓冲整个文件绝不是一个好主意。 while 循环只会执行一次,因为整个文件都被读入缓冲区。为什么还要使用循环?
  • 现在发现,澄清文件类型,将删除循环,我的错误@alvits