在 C 中加入或合并文件

问题描述 投票:0回答:1

我正在使用 Curl 从互联网下载文件。如果文件很大,通过使用 Range 标头,我将其分成 3 个块,然后分别下载它们,从而与同一 URL 建立多个连接。现在的问题是,我如何将这 3 个不同的块重新连接到一个大文件中?在互联网上搜索我发现的所有内容都是使用 fgetc、fgets 等将数据解释为文本文件来合并文本文件。但我的文件主要是视频文件或大 iso 文件,因此是二进制数据。我查看了 fwrite 但我怎么知道哪个大小是一个元素?这只是二进制数据。我很困惑。 写入各个块的 Curl 例程如下:

size_t write_data(void *ptr, size_t sz, size_t nmemb, FILE *stream) { size_t written = fwrite(ptr, sz, nmemb, stream); return written; }
假设我下载了这 3 个块,filepath1.x、filepath2.x、filepath3.x,我如何将它们合并到 output.mp4 中?

c file join merge
1个回答
0
投票

既然你无论如何都在使用 shell 实用程序,那么最简单的方法就是使用

cat
cat file1.x file2.x file3.x > file.x

如果您想在纯 C 中执行此操作,请使用

fopen
但切换为读取二进制文件。文本与二进制只是 Windows 上的一个问题。 POSIX 系统(Unix 和 MacOS)没有区别。

可以选择指定文件访问模式标志“b”以二进制模式打开文件。该标志对 POSIX 系统没有影响,但在 Windows 上它会禁用 ' ' 和 '\x1A'。

如果这只是一个小实用程序,请打印到标准输出并使用 shell 管道将输出重定向到文件。就像

cat
一样。

我们通过分配固定缓冲区来读取每个文件,并在该缓冲区中读取和写入块。我喜欢使用

BUFSIZ
常量,因为它可能与系统的块大小相同,这使得读取更加高效。 4096 也是一个不错的值,4k 是常见的块大小。

fread
fwrite
是奇数。我们需要告诉他们读取 X 个 Y 大小的对象,而不是仅仅告诉他们要读取多少。这是“面向记录的文件系统”的延续,当您读取固定大小的对象列表时最有用。由于 C 字符串是 1 字节字符的数组,因此我们要读取 1 字节 N 次。

fread

返回读取的对象数量。我们正在读取 1 字节对象,因此这相当于字节数。我们将该金额写为

fwrite
。如果 BUFSIZ 是 4096 字节,但文件只有 50 字节,我们只会写入 50 字节,而不是 50 字节加上 4046 字节的垃圾。
#include <stdio.h>
#include <string.h>
#include<unistd.h>
#include <errno.h>

int main(int argc, char *argv[]) {
    // Allocate a buffer for reading.
    char buf[BUFSIZ];

    // Or FILE *output = fopen(output_file, "wb")
    FILE *output = stdout;

    // Iterate through the filenames given on the command line.
    for( int i = 1; argv[i] != NULL; i++ ) {
        // Open the file for binary reading.
        char *filename = argv[i];
        FILE *f = fopen(filename, "rb");
        if( f == NULL ) {
            fprintf(stderr, "Could not open %s: %s\n", filename, strerror(errno));
        }

        // Read a BUFSIZ chunk, write it to the output.
        size_t bytes_read;
        while( (bytes_read = fread(buf, 1, sizeof(buf), f)) > 0 ) {
            fwrite(buf, 1, bytes_read, output);
        }

        // Close the input file.
        fclose(f);
    }

    if( output != stdout ) {
        fclose(output);
    }
}

© www.soinside.com 2019 - 2024. All rights reserved.