什么是最简单的方法(最不容易出错,最少的代码行,但是你想要解释它)在C中打开一个文件并将其内容读入一个字符串(char*,char [],等等)?
我倾向于将整个缓冲区作为原始内存块加载到内存中并自行进行解析.这样我就可以最好地控制标准库在多个平台上的功能.
这是我用于此的存根.您可能还想检查fseek,ftell和fread的错误代码.(为清楚起见,省略).
char * buffer = 0; long length; FILE * f = fopen (filename, "rb"); if (f) { fseek (f, 0, SEEK_END); length = ftell (f); fseek (f, 0, SEEK_SET); buffer = malloc (length); if (buffer) { fread (buffer, 1, length, f); } fclose (f); } if (buffer) { // start to process your data / extract strings here... }
另一个不幸的是高度依赖操作系统的解决方案是内存映射文件.优点通常包括读取的性能和减少的内存使用,因为应用程序视图和操作系统文件缓存实际上可以共享物理内存.
POSIX代码如下所示:
int fd = open("filename", O_RDONLY); int len = lseek(fd, 0, SEEK_END); void *data = mmap(0, len, PROT_READ, MAP_PRIVATE, fd, 0);
另一方面,Windows稍微有点棘手,不幸的是我没有在我面前测试编译器,但功能是由CreateFileMapping()
和提供的MapViewOfFile()
.
如果"将其内容读入字符串"意味着该文件不包含代码为0的字符,则还可以使用getdelim()函数,该函数接受内存块并在必要时重新分配,或者仅为整个缓冲区分配您,并将文件读入其中,直到遇到指定的分隔符或文件结尾.只需传递'\ 0'作为分隔符即可读取整个文件.
该功能在GNU C库中可用,http://www.gnu.org/software/libc/manual/html_mono/libc.html#index-getdelim-994
示例代码可能看起来很简单
char* buffer = NULL; size_t len; ssize_t bytes_read = getdelim( &buffer, &len, '\0', fp); if ( bytes_read != -1) { /* Success, now the entire file is in the buffer */
如果文件是文本,并且您想逐行获取文本,最简单的方法是使用fgets().
char buffer[100]; FILE *fp = fopen("filename", "r"); // do not use "rb" while (fgets(buffer, sizeof(buffer), fp)) { ... do something } fclose(fp);
如果您正在读取stdin或管道等特殊文件,则无法事先使用fstat来获取文件大小.此外,如果您正在读取二进制文件,则由于嵌入的"\ 0"字符,fgets将丢失字符串大小信息.读取文件的最佳方法是使用read和realloc:
#include#include #include #include int main () { char buf[4096]; ssize_t n; char *str = NULL; size_t len = 0; while (n = read(STDIN_FILENO, buf, sizeof buf)) { if (n < 0) { if (errno == EAGAIN) continue; perror("read"); break; } str = realloc(str, len + n + 1); memcpy(str + len, buf, n); len += n; str[len] = '\0'; } printf("%.*s\n", len, str); return 0; }