Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C编程:如何将整个文件内容读入缓冲区_C_File Io - Fatal编程技术网

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;
}