C编程:如何将整个文件内容读入缓冲区

我想将一个文件的全部内容写入一个缓冲区。 该文件实际上只包含一个string,我需要比较一个string。

什么是最有效的select,即使在Linux上也是可移植的。

ENV:Windows

Linux和Windows之间的可移植性令人头痛,因为Linux是符合POSIX规范的系统,一般来说C是一个适当的,高质量的工具链,而Windows甚至在C标准库中甚至没有提供很多的function。

但是,如果你想坚持这个标准,你可以写这样的东西:

#include <stdio.h> #include <stdlib.h> FILE *f = fopen("textfile.txt", "rb"); fseek(f, 0, SEEK_END); long fsize = ftell(f); fseek(f, 0, SEEK_SET); //same as rewind(f); char *string = malloc(fsize + 1); fread(string, fsize, 1, f); fclose(f); string[fsize] = 0; 

这里string将包含文本文件的内容作为正确的0结尾的Cstring。 这个代码只是标准的C,它不是POSIX特定的(尽pipe它不保证它将在Windows上工作/编译…)

如果您提前知道最大缓冲区大小:

 #include <stdio.h> #define MAXBUFLEN 1000000 char source[MAXBUFLEN + 1]; FILE *fp = fopen("foo.txt", "r"); if (fp != NULL) { size_t newLen = fread(source, sizeof(char), MAXBUFLEN, fp); if (newLen == 0) { fputs("Error reading file", stderr); } else { source[++newLen] = '\0'; /* Just to be safe. */ } fclose(fp); } 

或者,如果您不这样做:

 #include <stdio.h> #include <stdlib.h> char *source = NULL; FILE *fp = fopen("foo.txt", "r"); if (fp != NULL) { /* Go to the end of the file. */ if (fseek(fp, 0L, SEEK_END) == 0) { /* Get the size of the file. */ long bufsize = ftell(fp); if (bufsize == -1) { /* Error */ } /* Allocate our buffer to that size. */ source = malloc(sizeof(char) * (bufsize + 1)); /* Go back to the start of the file. */ if (fseek(fp, 0L, SEEK_SET) != 0) { /* Handle error here */ } /* Read the entire file into memory. */ size_t newLen = fread(source, sizeof(char), bufsize, fp); if (newLen == 0) { fputs("Error reading file", stderr); } else { source[++newLen] = '\0'; /* Just to be safe. */ } } fclose(fp); } free(source); /* Don't forget to call free() later! */ 

这是我会推荐的。

它应该符合C89,并且是完全便携的。 特别是,它也适用于POSIXy系统上的pipe道和sockets。

我们的想法是,我们读大块( READALL_CHUNK )的input,dynamic重新分配缓冲区,因为我们需要它。 我们只使用realloc()fread()ferror()free()

 #include <stdlib.h> #include <stdio.h> #include <errno.h> /* Size of each input chunk to be read and allocate for. */ #ifndef READALL_CHUNK #define READALL_CHUNK 262144 #endif #define READALL_OK 0 /* Success */ #define READALL_INVALID -1 /* Invalid parameters */ #define READALL_ERROR -2 /* Stream error */ #define READALL_TOOMUCH -3 /* Too much input */ #define READALL_NOMEM -4 /* Out of memory */ /* This function returns one of the READALL_ constants above. If the return value is zero == READALL_OK, then: (*dataptr) points to a dynamically allocated buffer, with (*sizeptr) chars read from the file. The buffer is allocated for one extra char, which is NUL, and automatically appended after the data. Initial values of (*dataptr) and (*sizeptr) are ignored. */ int readall(FILE *in, char **dataptr, size_t *sizeptr) { char *data = NULL, *temp; size_t size = 0; size_t used = 0; size_t n; /* None of the parameters can be NULL. */ if (in == NULL || dataptr == NULL || sizeptr == NULL) return READALL_INVALID; /* A read error already occurred? */ if (ferror(in)) return READALL_ERROR; while (1) { if (used + READALL_CHUNK + 1 > size) { size = used + READALL_CHUNK + 1; /* Overflow check. Some ANSI C compilers may optimize this away, though. */ if (size <= used) { free(data); return READALL_TOOMUCH; } temp = realloc(data, size); if (temp == NULL) { free(data); return READALL_NOMEM; } data = temp;    } n = fread(data + used, 1, READALL_CHUNK, in); if (n == 0) break; used += n; } if (ferror(in)) { free(data); return READALL_ERROR; } temp = realloc(data, used + 1); if (temp == NULL) { free(data); return READALL_NOMEM; } data = temp; data[used] = '\0'; *dataptr = data; *sizeptr = used; return READALL_OK; } 

上面,我使用了一个常量块大小, READALL_CHUNK == 262144( 256*1024 )。 这意味着在最坏的情况下,多达262145个字符被浪费(分配但未被使用),但只是暂时的。 最后,函数将缓冲区重新分配给最佳的大小。 另外,这意味着我们每读取一个数据字节就有四次重新分配。

上面代码中的262144字节默认值是一个保守值; 对于即使是旧的小型机器和树莓派也是如此,而且大多数embedded式设备至less拥有几兆字节的RAM。 然而,它并不是很小,所以在大多数系统上它会减缓操作(由于许多读取调用和许多缓冲区重新分配)。

对于目前的桌面计算机(2017),我推荐一个更大的READALL_CHUNK ,也许是#define READALL_CHUNK 2097152 (2 MiB)。

因为READALL_CHUNK的定义是被保护的(也就是说,只有在代码中的那个时刻才定义),你可以在编译时通过使用(在大多数C编译器中) -DREADALL_CHUNK=2097152命令覆盖默认值-line选项 – 但请检查您的编译器选项,以使用命令行选项定义预处理器macros。

便携式解决scheme可以使用getc

 #include <stdio.h> char buffer[MAX_FILE_SIZE]; size_t i; for (i = 0; i < MAX_FILE_SIZE; ++i) { int c = getc(fp); if (c == EOF) { buffer[i] = 0x00; break; } buffer[i] = c; } 

如果你不想拥有一个MAX_FILE_SIZEmacros,或者它是一个很大的数字(例如buffer大到适合堆栈),就使用dynamic分配。