C编程:如何将整个文件内容读入缓冲区
我想将文件的全部内容写入缓冲区。该文件实际上只包含一个字符串,我需要将其与字符串进行比较C编程:如何将整个文件内容读入缓冲区,c,file-io,C,File Io,我想将文件的全部内容写入缓冲区。该文件实际上只包含一个字符串,我需要将其与字符串进行比较 即使在linux上也是可移植的最有效的选项是什么 ENV:Windows便携式解决方案可以使用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) {
即使在linux上也是可移植的最有效的选项是什么
ENV:Windows便携式解决方案可以使用
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;
}
#包括
字符缓冲区[最大文件大小];
尺寸i;
对于(i=0;i
如果你不想拥有一个
MAX\u FILE\u SIZE
宏,或者如果它是一个很大的数字(比如缓冲区
太大了,无法放在堆栈上),请使用动态分配。Linux和Windows之间的可移植性是一个大问题,因为Linux是一个符合POSIX的系统,通常是一个适合C的高质量工具链,而Windows甚至没有在C标准库中提供很多函数
但是,如果你想坚持标准,你可以这样写:
#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, 1, fsize, f);
fclose(f);
string[fsize] = 0;
#包括
#包括
FILE*f=fopen(“textfile.txt”、“rb”);
fseek(f,0,SEEK_END);
长fsize=ftell(f);
fseek(f,0,SEEK_集);/*与倒带(f)相同*/
char*string=malloc(fsize+1);
fread(字符串,1,fsize,f);
fclose(f);
字符串[fsize]=0;
此处
string
将文本文件的内容作为正确的以0结尾的C字符串包含。这段代码只是标准的C,它不是特定于POSIX的(尽管它不能保证它能在Windows上工作/编译…)以下是我的建议
它应该符合C89的要求,并且是完全便携式的。特别是,它也适用于POSIXy系统上的管道和插座
我们的想法是以大的ish块(READALL\u CHUNK
)读取输入,根据需要动态地重新分配缓冲区。我们只使用realloc()
,fread()
,ferror()
,和free()
:
#包括
#包括
#包括
/*要删除的每个输入块的大小
阅读并分配*/
#ifndef READALL\u块
#定义READALL_块262144
#恩迪夫
#定义READALL_OK 0/*成功*/
#定义READALL_INVALID-1/*无效参数*/
#定义READALL_错误-2/*流错误*/
#定义READALL_Toomo-3/*输入太多*/
#定义READALL_NOMEM-4/*内存不足*/
/*此函数返回上述READALL_uu常量之一。
如果返回值为零==READALL_OK,则:
(*dataptr)指向动态分配的缓冲区,其中
(*sizeptr)从文件中读取的字符。
缓冲区被分配给一个额外的字符,即NUL,
并自动附加在数据之后。
忽略(*dataptr)和(*sizeptr)的初始值。
*/
int readall(文件*in,字符**dataptr,大小*sizeptr)
{
char*data=NULL,*temp;
大小\u t大小=0;
使用的大小=0;
尺寸;
/*所有参数都不能为NULL*/
if(in==NULL | | dataptr==NULL | | sizeptr==NULL)
返回READALL\u无效;
/*是否已发生读取错误*/
如果(铁(in))
返回READALL_错误;
而(1){
如果(已使用+读取所有内容块+1>大小){
大小=已使用+读取所有\u块+1;
/*溢出检查。一些ANSI C编译器
不过,这可能会优化掉*/
if(size)“即使在linux上也是可移植的”应该是“即使在Windows上也是可移植的”…我正在Windows上编写代码,希望在linux alsoSo上进行移植,您尝试了什么?您不需要将文件读入缓冲区来与字符串进行比较。最好是动态执行。第二,小心编码。在Windows上,有一些可笑的流行编码,例如UTF-16。最好在堆上分配大量内存块。另外,请不要逐字节读取,我相信在任何合适的libc实现中,fread()。此外,我不喜欢在Windows上使用POSIX函数,例如fread
,因为此操作系统的POSIX实现通常与规范不同。关于堆分配,我在回答的最后写了一段。fread()
不是特定于POSIX的。如果您不喜欢使用它,您可以放弃fgetc()
也是。为了防止任何访问者产生疑问,倒带(f);
相当于fseek(f,0,SEEK_SET);
可以在这里使用。这两者都是
哦的一部分,在指出之前:必须始终检查malloc()和fread()的返回值
。这里,仅为简单起见,省略了错误检查-不要将此代码逐字复制到生产代码库中。不要忘记释放()
字符串。实际上,此解决方案不符合标准;标准规定“二进制流不需要有意义地支持fseek
调用,其whence值为SEEK\u END
”,并且“将文件位置指示器设置为文件末尾,与fseek(file,0,SEEK\u END)
一样,对于二进制流具有未定义的行为”。可能fsize=fread(string,1,fsize,f);会更好,以防它没有被完全阅读。投票支持不寻求file@ElvissStrazdins:谢谢;这正是我提到这一条适用于管道和插座的原因——它们根本不可查找。你认为我是否应该添加一段关于seek方法如何不适用于这些管道和插座的内容
方法,顺便提一下。)在读取失败之前读取流实际上是唯一一个可移植的选项,它可以处理文件
句柄上的所有内容
#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;
}