4

我需要读取文件并将它们存储在 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 个循环(第一个将读取和计数,第二个将读取)对于大文件来说效率低且速度慢。需要以一种或其他更有效的方式来完成。请帮忙!不知道!

4

7 回答 7

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

但是,真的,担心效率的时候是在它工作得太慢之后。

于 2013-04-21T09:29:36.103 回答
5

如果这确实是一个需要优化的地方,那么你真正应该优化的是以下两点:

  • 缓冲区分配
  • 来电次数read()write()

对于 100 到 1000 字节的小缓冲区,没有理由使用malloc()之类的,只需在堆栈上分配缓冲区,它会是最快的。当然,除非您想从函数返回指向这些缓冲区的指针,在这种情况下您可能应该使用malloc(). 否则,您应该考虑使用全局/静态数组而不是动态分配的数组。

至于 I/O 调用,调用read()write()使用整个缓冲区大小。不要调用它们来读取或写入单个字节。转换到内核并返回确实有成本。

此外,如果您希望需要在 RAM 中处理相当大的文件,请考虑使用文件映射。

于 2013-04-21T09:29:26.603 回答
4

stat等。允许您获取文件大小。http://linux.die.net/man/2/fstat

或者,如果你不能使用, http: lseek //linux.die.net/man/2/lseek(特别注意返回值)

如果你也不能使用它,你可以随时使用realloc你的缓冲区。

我把它留给你来实施,因为这显然是一项任务。;)

于 2013-04-21T09:29:01.057 回答
2

在优化任何东西之前,您必须分析您的代码。有很多工具可以做到这一点:

  • 瓦尔格林
  • 英特尔 VTune
  • 时间
  • AMD 代码分析器
于 2013-04-21T09:44:43.157 回答
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;
}
于 2013-04-21T10:04:04.887 回答
0

为什么你需要内存中的所有内容?您可以进行大块读取、处理、读取下一个块等,
除非您有足够的内存,否则您无法将所有内容都保留在您的 buff 中。你的目标是什么?

于 2013-04-21T09:30:27.767 回答
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!

brkandsbrk函数使您可以直接访问 malloc 使用的同一堆。但是没有任何 malloc 的“开销”。并且没有任何 malloc 的功能,例如free, reallocsbrk以字节为单位调用并返回一个void *. brk使用指针值调用(即,您只是想象指针存在并以某种方式将其声明brk),并返回void *.

通过使用brkor分配内存,它使用的空间与 malloc 在第一次调用orsbrk时尝试设置和使用的空间相同。并且许多库函数在后台使用 malloc ,因此有很多方法可以破坏此代码。这是一个非常奇怪和有趣的领域。mallocrealloc

这里的信号处理器也很危险。它会自动为您提供无限空间,但是当然,如​​果您遇到任何其他类型的分段违规,例如取消引用 NULL 指针,处理程序将无法修复该问题,并且它不会再崩溃。所以这会使程序进入一个讨厌的循环:重试内存访问,分配更多空间,重试内存访问,分配更多空间。

于 2013-04-21T09:46:55.503 回答