首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C编程:如何将整个文件内容读入缓冲区

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

Stack Overflow用户
提问于 2012-12-22 20:45:50
回答 3查看 229.2K关注 0票数 96

我想要将一个文件的全部内容写入一个缓冲区。该文件实际上只包含一个字符串,我需要将其与字符串进行比较。

最有效的选择是什么,即使在linux上也是可移植的。

环境: Windows

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-12-22 20:51:41

Linux和Windows之间的可移植性是一个令人头疼的问题,因为Linux是一个符合POSIX的系统,通常具有一个适当的、高质量的C工具链,而Windows甚至没有在C标准库中提供很多函数。

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

代码语言:javascript
复制
#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;

在这里,string将包含文本文件的内容,它是一个以0结尾的C字符串。这段代码只是标准的C语言,而不是特定于POSIX的(尽管它不能保证它能在Windows上工作/编译...)

票数 190
EN

Stack Overflow用户

发布于 2017-07-04 07:22:24

以下是我推荐的内容。

它应该符合C89,并且是完全可移植的。特别是,它还适用于POSIXy系统上的管道和套接字。

其思想是,我们以大块(READALL_CHUNK)读取输入,在需要时动态地重新分配缓冲区。我们只使用realloc()fread()ferror()free()

代码语言:javascript
复制
#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字节默认值是一个保守的值;即使是旧的小型笔记本电脑和树莓派,以及大多数至少有几兆字节RAM可用于该进程的嵌入式设备,它也能很好地工作。然而,它并不小到会减慢大多数系统上的操作(由于许多读取调用和许多缓冲区重新分配)。

对于目前(2017年)的台式机,我推荐更大的READALL_CHUNK,也许是#define READALL_CHUNK 2097152 (2 MiB)。

因为READALL_CHUNK的定义是受保护的(即,只有当它在代码中仍未定义时才被定义),您可以在编译时通过使用(在大多数C编译器中) -DREADALL_CHUNK=2097152命令行选项来覆盖默认值--但是一定要检查您的编译器选项,以便使用命令行选项定义预处理器宏。

票数 35
EN

Stack Overflow用户

发布于 2012-12-22 20:50:09

可移植的解决方案可以使用getc

代码语言:javascript
复制
#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_SIZE宏,或者如果它是一个很大的数字(这样buffer就会太大而无法放在堆栈中),那么可以使用动态分配。

票数 -3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14002954

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档