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

C语言实现文件内容多次复制时出现乱码且仅复制一次的问题排查

Troubleshooting Your File Copy Program: Fixing Garbled Output & Repeated Copy Failures

Let’s walk through the key issues in your code that are causing the garbled output and failed repeated copies—these are all common pitfalls when working with C file I/O, so don’t worry, we’ll get it sorted:

1. Critical: get_size() Has No Return Value

You declared this function to return an int, but there’s no return len; statement at the end! When you call size = get_size(argv[1]); in main(), size ends up with a random garbage value, which breaks every subsequent operation that relies on the source file’s actual length.

Fix:
Add the missing return statement, plus error handling for failed file opens:

int get_size(char* filepath) {
    FILE* f = fopen(filepath,"rb");
    if (!f) { // Check if file opened successfully
        fprintf(stderr, "Failed to open file: %s\n", filepath);
        return -1;
    }
    fseek(f,0,SEEK_END);
    int len = ftell(f);
    fclose(f);
    printf("TOTAL SIZE THAT SHOULD BE IN THE FUNCTION IS %d\n", len);
    return len; // Return the calculated length!
}

2. write_correctly() Is Full of Breaking Mistakes

This function is the main culprit behind your issues:

  • Wrong open flags: You used O_APPEND || O_CREAT (logical OR, which evaluates to 1) instead of O_APPEND | O_CREAT (bitwise OR, the correct way to combine flags). Also, when using O_CREAT, you must specify file permissions (like 0644)—otherwise, new files get random invalid permissions.
  • Writing the wrong length: You’re trying to write the target file’s current length (len_to_use = get_size(file)) instead of the source file’s content length (len). This is why you’re getting garbled data—you’re writing random amounts of garbage.
  • Unchecked file descriptor: open() can fail (e.g., due to permissions), but you don’t check if file_descriptor is -1 before calling write().
  • Incorrect success check: You compare size != len, but size is the bytes written using the wrong len_to_use value—this check is meaningless.

Fix:

int write_correctly(char* file, char* buffer, int len) {
    if (len <= 0 || !buffer) {
        fprintf(stderr, "Invalid buffer or length\n");
        return -1;
    }
    // Correct open mode: append, create if missing, write-only, with valid permissions
    int file_descriptor = open(file, O_APPEND | O_CREAT | O_WRONLY, 0644);
    if (file_descriptor == -1) {
        fprintf(stderr, "Failed to open target file: %s\n", file);
        return -1;
    }
    // Write the full source content (len bytes)
    ssize_t written = write(file_descriptor, buffer, len);
    printf("Wrote %zd bytes\n", written);
    close(file_descriptor);
    // Verify all bytes were written
    if (written != len) {
        fprintf(stderr, "Only wrote %zd of %d bytes\n", written, len);
        return -1;
    }
    return written;
}

3. laod_with_correct_size() Minor (But Important) Fixes

  • Unnecessary parameter: The size parameter is immediately set to 0 and never used—you can remove it entirely.
  • Dangerous fclose(NULL): If fopen() fails, file is NULL, and calling fclose(file) causes undefined behavior (crash). Remove that line.
  • Spelling error: laod → load (doesn’t break code, but improves readability).

Fix:

char* load_with_correct_size(char* file_location) {
    char* buffer = NULL;
    FILE* file = fopen(file_location, "rb");
    if (file == NULL) {
        fprintf(stderr, "Failed to open source file: %s\n", file_location);
        return NULL;
    }
    fseek(file, 0, SEEK_END);
    int len = ftell(file);
    if (len < 1) {
        fclose(file);
        fprintf(stderr, "Source file is empty\n");
        return NULL;
    }
    rewind(file);
    buffer = (char*)malloc(len);
    if (buffer == NULL) {
        fclose(file);
        fprintf(stderr, "Malloc failed\n");
        return NULL;
    }
    if (fread(buffer, 1, len, file) != (size_t)len) {
        free(buffer);
        fclose(file);
        fprintf(stderr, "Failed to read entire source file\n");
        return NULL;
    }
    fclose(file);
    printf("Size in function is %d\n", len);
    return buffer;
}

4. main() Needs Error Checking & Cleanup

You don’t verify if the user provided both source and target file paths (if argc != 3, argv[1]/argv[2] will be NULL and crash the program). Also, you never free the buffer allocated with malloc()—this causes memory leaks.

Fix:

int main(int argc, char** argv) {
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <source_file> <target_file>\n", argv[0]);
        return 1;
    }
    int size = get_size(argv[1]);
    if (size <= 0) {
        fprintf(stderr, "Failed to get source file size\n");
        return 1;
    }
    char* buffer = load_with_correct_size(argv[1]);
    if (!buffer) {
        fprintf(stderr, "Failed to load source file\n");
        return 1;
    }
    printf("Size of %s is %d\n", argv[1], size);
    // Repeat write 4 times
    for (int i = 0; i < 4; i++) {
        if (write_correctly(argv[2], buffer, size) < 0) {
            printf("Copy iteration %d failed\n", i+1);
        }
    }
    free(buffer); // Clean up allocated memory
    return 0;
}

Why Your Original Code Failed

  • The missing return in get_size() meant all length values were garbage, leading to incorrect write lengths and garbled data.
  • The wrong open() flags caused unexpected file behavior, and writing the target file’s length instead of the source’s led to random garbage being appended after the first copy.

内容的提问来源于stack exchange,提问作者Rares Amza

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 16:57:49