我需要读取文件并将它们存储在mainbuff和mainbuff2中。
我应该只使用open()
,read()
,write()
等系统调用。
我不想将它们存储在堆栈中,如果它会非常大的话呢?堆分配更好。
此代码有效:
...
char charbuf;
char *mainbuff1=malloc(100);
char *mainbuff2=malloc(100);
while (read(file1, &charbuf, 1)!=0)
mainbuff1[len++]=charbuf;
while (read(file2, &charbuf, 1)!=0)
mainbuff2[len2++]=charbuf;
...
但是mainbuff只有100个字符。更好的解决方案是在计算文件中的字符后分配mainbuff,如下所示:
...
char charbuf;
while (read(file1, &charbuf, 1)!=0)
len++;
while (read(file2, &charbuf, 1)!=0)
len2++;
char *mainbuff1=malloc(len);
char *mainbuff2=malloc(len2);
...
然后再次重复while
循环并将字节读入mainbuff。
但是2个循环(第一个将读取并计数,第二个将读取)对于大型文件将是无效且慢的。需要在一个或更高效的其他方面做到这一点。请帮忙!不知道!
答案 0 :(得分:7)
您可以使用fstat
来获取文件大小,而不是阅读两次。
#include <sys/stat.h>
int main() {
struct stat sbuf;
int fd = open("filename", O_RDWR);
fstat(fd, &sbuf);
char *buf = malloc(sbuf.st_size + 1);
}
但是,实际上,担心效率的时间是工作太慢。
答案 1 :(得分:5)
如果这确实是需要优化的地方,那么你真正应该优化的是以下两件事:
read()
和write()
对于100到1000字节的小缓冲区,没有理由使用malloc()
之类的东西,只需在堆栈上分配缓冲区,它就会是最快的。当然,除非你想从函数返回指向这些缓冲区的指针,在这种情况下你可能应该使用malloc()
。否则,您应该考虑使用全局/静态数组而不是动态分配的数组。
对于I / O调用,请使用整个缓冲区大小调用read()
和write()
。不要让它们读取或写入单个字节。转换到内核和返回确实有成本。
此外,如果您希望在RAM中使用相当大的文件,请考虑使用文件映射。
答案 2 :(得分:4)
stat
等。允许您获取文件大小。 http://linux.die.net/man/2/fstat
或者,如果你不能使用它,lseek
http://linux.die.net/man/2/lseek(特别注意返回值)
如果你也不能使用它,你可以随时realloc
你的缓冲区。
我要由你来实施它,因为这显然是一项任务。 ;)
答案 3 :(得分:2)
在优化任何内容之前,您必须分析您的代码。有许多工具可以做到这一点:
答案 4 :(得分:1)
定义一个自动直接扩展的数组。 像这样
#include <stdio.h>
#include <stdlib.h>
typedef struct dynarray {
size_t size;
size_t capacity;
char *array;
} DynArray;
DynArray *da_make(size_t init_size){
DynArray *da;
if(NULL==(da=(DynArray*)malloc(sizeof(DynArray)))){
perror("memory not enough");
exit(-1);
}
if(NULL==(da->array=(char*)malloc(sizeof(char)*init_size))){
perror("memory not enough");
exit(-1);
}
da->size = 0;
da->capacity=init_size;
return da;
}
void da_add(DynArray *da, char value){
da->array[da->size] = value;
if(++da->size == da->capacity){
da->array=(char*)realloc(da->array, sizeof(char)*(da->capacity += 1024));
if(NULL==da){
perror("memory not enough");
exit(-1);
}
}
}
void da_free(DynArray *da){
free(da->array);
free(da);
}
int main(void) {
DynArray *da;
char charbuf;
int i;
da = da_make(128);
while(read(0, &charbuf, 1)!=0)
da_add(da, charbuf);
for(i=0;i<da->size;++i)
putchar(da->array[i]);
da_free(da);
return 0;
}
答案 5 :(得分:0)
为什么你需要记忆中的一切?你可以有大量的读取,处理,读取下一个块等,
除非你有足够的记忆力,否则你无法将所有记忆保持在你的身上。你的目标是什么?
答案 6 :(得分:0)
正如您所说,如果您只使用系统调用,您可以将整个堆用作缓冲区。
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
size_t sz;
void fix(x){signal(SIGSEGV,fix);sbrk(sz *= 2);}
int main() {
sz = getpagesize();
signal(SIGSEGV,fix);
char *buf = sbrk(sz);
int fd = open("filename", O_RDWR);
read(fd, buf, -1);
}
但是如果你碰巧调用了一个使用malloc的库函数,Kablooey!
brk
和sbrk
函数使您可以直接访问malloc使用的同一堆。但没有任何malloc的“开销”。并且没有任何malloc的功能,例如free
,realloc
。调用sbrk
,其大小以字节为单位,并返回void *
。使用指针值调用brk
(即,您只是想象指针存在并且将声明到某个方式),并返回brk
。
通过使用void *
或brk
分配内存,它使用的mallati将尝试在第一次调用sbrk
或malloc
时尝试设置和使用相同的空间。许多库函数使用malloc 引擎,因此这个代码有很多方法可以解决。这是一个非常奇怪而有趣的领域。
此处的信号处理程序也非常危险。它为您提供自动无限空间,但当然,如果您遇到任何其他类型的分段违规,例如解除引用NULL指针,处理程序无法修复它,并且它不会再崩溃。所以这可以将程序发送到一个讨厌的循环:重试内存访问,分配更多空间,重试内存访问,分配更多空间。