使用UNIX API调用读取文件时出现额外随机字符问题求助
Let's tackle these two Unix file I/O problems you're facing—they're both classic pitfalls when working with raw system calls instead of the standard C stdio library, so you’re in good company!
1. Extra random characters when using read() to print file content
Root Cause
The read() system call deals with raw bytes—it doesn’t automatically add a null terminator (\0) at the end of the data it reads. When you pass the buffer to printf("%s"), the function will keep reading memory until it hits a \0, which leads to those random garbage characters after your actual file content.
Fix
Always use the return value of read() to track how many bytes were actually read, then manually add a null terminator at the correct position. Also, leave extra space in your buffer to avoid overflow when adding the terminator.
Here’s a fixed code example:
#include <unistd.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> int main() { int fd = open("target.txt", O_RDONLY); if (fd == -1) { perror("Failed to open file"); exit(EXIT_FAILURE); } // Reserve 1 extra byte for the null terminator char buf[1024]; ssize_t bytes_read = read(fd, buf, sizeof(buf) - 1); if (bytes_read == -1) { perror("Failed to read file"); close(fd); exit(EXIT_FAILURE); } // Null-terminate the actual data we read buf[bytes_read] = '\0'; printf("%s", buf); close(fd); return 0; }
2. Garbage characters in custom OpenRead() function for file comparison
Root Cause
This usually stems from a few combined issues:
- Not allocating enough memory to hold the full file content plus a null terminator
- Not looping to read the entire file (
read()might only return partial data in one call) - Forgetting to add a null terminator to the returned string
- Mishandling file size calculation, leading to memory overflow
Fix
Your OpenRead() function needs to properly handle file size, memory allocation, full file reading, and null termination. Here’s a robust implementation:
#include <unistd.h> #include <fcntl.h> #include <sys/stat.h> #include <stdlib.h> #include <stdio.h> #include <string.h> char* OpenRead(const char* filename) { // Open the file and check for errors int fd = open(filename, O_RDONLY); if (fd == -1) { perror("OpenRead: Failed to open file"); return NULL; } // Get the file size using fstat struct stat file_stats; if (fstat(fd, &file_stats) == -1) { perror("OpenRead: Failed to get file stats"); close(fd); return NULL; } // Allocate memory for content + null terminator char* content = malloc(file_stats.st_size + 1); if (!content) { perror("OpenRead: Failed to allocate memory"); close(fd); return NULL; } // Read the entire file (loop in case read returns partial bytes) ssize_t total_read = 0; while (total_read < file_stats.st_size) { ssize_t bytes_read = read(fd, content + total_read, file_stats.st_size - total_read); if (bytes_read == -1) { perror("OpenRead: Failed to read file content"); free(content); close(fd); return NULL; } total_read += bytes_read; } // Add null terminator to make it a valid C string content[total_read] = '\0'; close(fd); return content; } // Example file comparison program int main(int argc, char* argv[]) { if (argc != 3) { fprintf(stderr, "Usage: %s f1.txt f2.txt\n", argv[0]); exit(EXIT_FAILURE); } char* f1_content = OpenRead(argv[1]); char* f2_content = OpenRead(argv[2]); if (!f1_content || !f2_content) { exit(EXIT_FAILURE); } // Compare the file contents if (strcmp(f1_content, f2_content) == 0) { printf("Files are identical\n"); } else { printf("Files differ\n"); } // Clean up allocated memory to avoid leaks free(f1_content); free(f2_content); return 0; }
Compile this with gcc fileComp.c -o fileComp, then run ./fileComp f1.txt f2.txt—it should no longer produce garbage characters.
内容的提问来源于stack exchange,提问作者user9431482

