C语言实现文件内容多次复制时出现乱码且仅复制一次的问题排查
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 to1) instead ofO_APPEND | O_CREAT(bitwise OR, the correct way to combine flags). Also, when usingO_CREAT, you must specify file permissions (like0644)—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 iffile_descriptoris-1before callingwrite(). - Incorrect success check: You compare
size != len, butsizeis the bytes written using the wronglen_to_usevalue—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
sizeparameter is immediately set to0and never used—you can remove it entirely. - Dangerous
fclose(NULL): Iffopen()fails,fileisNULL, and callingfclose(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

