You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言实现类*NIX cp工具:MP4/MP3复制损坏问题求助

Fixing Binary File Corruption in Your C Pipe-Based cp Clone

Let's break down why your tool works for text files but breaks MP4/MP3s—this is a classic pitfall when dealing with binary vs text modes in C, plus some easy-to-miss pipe and buffer handling details.

The Root Cause(s)

  1. You're using text mode for file I/O
    When you open a file with fopen("path", "r") or "w", C uses text mode. On *NIX systems this is mostly harmless, but it still treats certain bytes (like 0x1A, the traditional EOF character) as a signal to stop reading. Binary files like MP4s are full of non-text bytes, so your code is likely truncating the file early when it hits one of these.

  2. You're writing the full buffer every time, even if you didn't read 250 bytes
    If your loop reads fewer than 250 bytes (which happens at the end of the file), writing the entire buffer will append garbage data to the end of your target file—this corrupts the file's header or metadata, which is why media players can't recognize it.

  3. Incorrect pipe file descriptor management
    If you don't close unused pipe ends in parent/child processes, your read calls might hang waiting for EOF, leaving the target file incomplete.

Step-by-Step Fixes

1. Switch to binary mode for file operations

Replace your fopen calls with binary mode flags:

// Open source file in binary read mode
FILE *src_fp = fopen(argv[1], "rb");
if (src_fp == NULL) { perror("Failed to open source file"); exit(1); }

// Open target file in binary write mode
FILE *dst_fp = fopen(argv[2], "wb");
if (dst_fp == NULL) { perror("Failed to open target file"); exit(1); }

This tells C to read/write every byte exactly as it is, no translations or early termination.

2. Respect the actual number of bytes read

Instead of assuming you always fill the 250-byte buffer, capture the return value of fread (or read for system calls) and write only that many bytes:

char buf[250];
size_t bytes_read;

// Read from source, write to pipe (parent process example)
while ((bytes_read = fread(buf, 1, sizeof(buf), src_fp)) > 0) {
    if (write(pipefd[1], buf, bytes_read) != bytes_read) {
        perror("Failed to write to pipe");
        exit(1);
    }
}

// In the child process: read from pipe, write to target
while ((bytes_read = read(pipefd[0], buf, sizeof(buf))) > 0) {
    if (fwrite(buf, 1, bytes_read, dst_fp) != bytes_read) {
        perror("Failed to write to target file");
        exit(1);
    }
}

This ensures you never write extra garbage data, and you handle the final partial buffer correctly.

3. Clean up pipe file descriptors

After forking, make sure each process closes the pipe ends it doesn't use. For example:

int pipefd[2];
if (pipe(pipefd) == -1) { perror("Pipe failed"); exit(1); }

pid_t pid = fork();
if (pid == 0) {
    // Child: reads from pipe, writes to target
    close(pipefd[1]); // Close unused write end
    // ... read/write logic ...
    close(pipefd[0]); // Clean up read end when done
    exit(0);
} else {
    // Parent: reads from source, writes to pipe
    close(pipefd[0]); // Close unused read end
    // ... read/write logic ...
    close(pipefd[1]); // Signal EOF to child by closing write end
    wait(NULL); // Wait for child to finish
}

Closing unused ends ensures that when the parent finishes writing, the child's read will get EOF and exit properly—no hanging, no incomplete files.

Verify the Fix

After making these changes, compare the size of the source and target files with ls -l. They should be identical. If they are, your media files should open correctly.

内容的提问来源于stack exchange,提问作者Kushagr Tyagi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:12:38