Linux文件复制到自研文件系统后末尾出现多余字符的求助
Hey there, let's break down why those weird extra characters are popping up at the end of your file when copying to your custom filesystem. The issue ties directly to how you're handling the file buffer and string termination—here's the breakdown and actionable fixes:
Key Problems in Your Code
- Missing Null Terminator for String Output: When you use
printf("\n%s", fileBuffer);, the%sformat expects a null-terminated string ('\0'at the end). But yourfileBufferis exactlyfileSizebytes long, andfreadonly fills it with the file's raw data—no extra space for a terminator. Soprintfreads past the buffer into random stack memory, spitting out those garbage characters. - Risky Stack Allocation for Large Files: Declaring
char fileBuffer[fileSize];as a local stack variable is dangerous iffileSizeis large—stack space is limited, and this could lead to crashes. - Incorrect Block Count Calculation:
fileSize/512uses integer division, which truncates any remainder. If your file size isn't a perfect multiple of 512, you'll miss the last partial block of data (not the cause of extra characters, but a critical bug to fix).
Step-by-Step Fixes
1. Use Heap Allocation for the Buffer (Add Null Terminator)
Replace the stack-allocated buffer with a heap-allocated one that has extra space for the null terminator:
// Allocate buffer with +1 for null terminator char *fileBuffer = malloc(fileSize + 1); if (fileBuffer == NULL) { printf("Memory allocation failed :("); fclose(file); return; }
After reading the file, add the null terminator before printing:
if (file != NULL) { size_t bytesRead = fread(fileBuffer, 1, fileSize, file); // Swapped parameters for better read tracking if (bytesRead != fileSize) { printf("Warning: Only read %zu of %ld bytes", bytesRead, fileSize); } fileBuffer[bytesRead] = '\0'; // Add null terminator here }
Don't forget to free the buffer when you're done:
assignBlocks(fileBuffer, node, (fileSize + 511) / 512); // Fix block count calculation free(fileBuffer);
2. Fix fread Parameters
Your original fread(fileBuffer, fileSize, 1, file); tries to read one chunk of fileSize bytes. Swapping the second and third parameters (fread(fileBuffer, 1, fileSize, file)) lets you track the exact number of bytes read, which helps with error checking and setting the null terminator correctly.
3. Correct Block Count Calculation
Instead of fileSize/512, use (fileSize + 511) / 512—this rounds up to the nearest whole number of 512-byte blocks, ensuring you don't lose partial data at the end of the file.
4. Avoid printf("%s") for Binary Files (Optional)
If your file might contain binary data (not just plain text), printf("%s") will stop at the first '\0' character. Instead, write the buffer directly to stdout with fwrite:
fwrite(fileBuffer, 1, fileSize, stdout);
Full Revised Code Snippet
void copyToFS(char *filePath, int currentDirectoryID) { printf("Enter file path: "); scanf("%s",filePath); int node = assignNode(filePath, 0, currentDirectoryID); long int fileSize = getFileSize(filePath); FILE *file = fopen(filePath, "r"); if (file == NULL) { printf("Could not open file :("); return; } printf("\nSize of : %ld", fileSize); // Allocate buffer with space for null terminator char *fileBuffer = malloc(fileSize + 1); if (fileBuffer == NULL) { printf("Memory allocation failed :("); fclose(file); return; } fseek(file, 0, SEEK_SET); size_t bytesRead = fread(fileBuffer, 1, fileSize, file); if (bytesRead != fileSize) { printf("\nWarning: Incomplete read - got %zu bytes instead of %ld", bytesRead, fileSize); } // Add null terminator for string operations fileBuffer[bytesRead] = '\0'; printf("\n%s", fileBuffer); // Calculate correct number of blocks (round up) int numBlocks = (fileSize + 511) / 512; assignBlocks(fileBuffer, node, numBlocks); free(fileBuffer); fclose(file); }
These changes should eliminate the extra garbage characters and fix other potential stability issues in your code.
内容的提问来源于stack exchange,提问作者karina

