【问题标题】:reading a text file into an array in c将文本文件读入c中的数组
【发布时间】:2010-09-29 11:36:57
【问题描述】:

将文本文件读入动态一维数组的最有效方法是什么?在每次读取字符后重新分配似乎很愚蠢,在每次读取行后重新分配似乎并没有好多少。我想将整个文件读入数组。你会怎么做?

【问题讨论】:

  • 我可能误解了你想要做什么:你想把整个文件读入一个大缓冲区,还是你想要一个每行都有一个条目的数组?

标签: c arrays


【解决方案1】:

我不太明白你想要什么。您是否要增量处理文件,从中读取一行,然后放弃并处理下一行?还是要将整个文件读入缓冲区?如果你想要后者,我认为这是合适的(在实际代码中检查 malloc 和 fopen 的 NULL 返回,以确定文件是否存在以及是否有足够的内存):

FILE *f = fopen("text.txt", "rb");
fseek(f, 0, SEEK_END);
long pos = ftell(f);
fseek(f, 0, SEEK_SET);

char *bytes = malloc(pos);
fread(bytes, pos, 1, f);
fclose(f);

hexdump(bytes); // do some stuff with it
free(bytes); // free allocated memory

【讨论】:

  • 是的,这适用于我的情况。我的意思是在每次读取字符后使用 realloc 似乎效率很低,同样在每次读取 \n 之后(以扩展数组)。
  • 您应该以二进制模式打开文件 - 否则可能会出现问题(检查例如 glibc 手册,12.17)
  • 嗨,有什么区别(假设我们使用 100 而不是 pos)char *bytes = malloc(100*sizeof(char));和上面你写 char *bytes = malloc(100); 的行第二个问题是,如果我的文件中有 180205962 个字符怎么办。上述读取文件的方式会有效吗?
  • @asel,第一个问题:sizeof(char)被定义为1,所以没有区别。第二个问题:不,您可能应该逐步阅读它(例如,逐行或其他一些分段方法)。否则,你的记忆会很快耗尽。
  • 使用 fseek/ftell 获取文件大小是不安全的。请参阅此 CERT 参考以了解原因以及如何安全地执行此操作:securecoding.cert.org/confluence/display/seccode/…
【解决方案2】:

如果您的系统上有mmap(2),您可以打开该文件并将其映射到内存中。这样,你就没有内存要分配,你甚至不必读取文件,系统会做。 您可以使用 litb 提供的 fseek() 技巧来获取大小

void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);

EDIT:您必须使用 lseek() 来获取文件的大小,.

int fd = open("filename", O_RDONLY);
int nbytes = lseek(fd, 0, SEEK_END);
void *content = mmap(NULL, nbytes, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);

【讨论】:

  • @saffsd 你有足够的代表来修复它,你知道它在这里是如何工作的。
  • 忘记了,修复并删除了评论。
  • 获取文件大小的一种可能更惯用的方法是使用 fstat(2) 函数:struct stat S; fstat(fd, &S);,然后 int nbytes = S.st_size 是文件大小(以字节为单位),直接来自文件系统,无需读取文件(这无疑会得到与上面相同的结果;我主要是为了完整性而提到它)。
【解决方案3】:

如果您想使用 ISO C,请使用this function

这是 litb 的答案,包含一些错误处理...

【讨论】:

    猜你喜欢
    • 2020-01-20
    • 1970-01-01
    • 2010-12-20
    • 1970-01-01
    • 1970-01-01
    • 2019-03-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多