【问题标题】:Dynamic char buffer C动态字符缓冲区 C
【发布时间】:2012-02-25 14:02:59
【问题描述】:

下面是我的代码的一部分,用于从文本文件中读取数据、去除 HTML 并仅打印出普通文本。这一切都很好,但我在阅读所有文本文件时遇到了问题。我将如何阅读整个文本文件,了解我可能需要使用 malloc 但不确定如何使用。

int i, nRead, fd;
int source;
char buf[1024];
int idx = 0;
int opened = 0;

if((fd = open("data.txt", O_RDONLY)) == -1)
{
    printf("Cannot open the file");
}
else
{
    nRead = read(fd, buf, 1024);
    printf("Original String ");
    for(i=0; i<nRead; i++)
    {
        printf("%c", buf[i]);
    }

    printf("\nReplaced String ");

    for(i=0; i<nRead; i++)
    {
        if(buf[i]=='<') {
            opened = 1;
        } else if (buf[i] == '>') {
            opened = 0;
        } else if (!opened) {
            buf[idx++] = buf[i];
        }           
        //printf("%c", buf[i]);
    }
}
    buf[idx] = '\0';
    printf("%s\n", buf);
close(source);

【问题讨论】:

  • 你必须循环调用read直到你得到0,跟踪你读过的数量,并将它附加到缓冲区;缓冲区需要根据需要增长,大概是通过realloc

标签: c linux malloc buffer


【解决方案1】:

如果您想阅读完整的文件,请执行以下操作:

  1. 打开文件
  2. 使用fstat - 请参阅fstat - 获取大小
  3. malloc 缓冲区即buffer = malloc(fileStats.st_size);
  4. 读取文件fread(buffer, fileStats.st_size, 1);
  5. 关闭文件。
  6. 尽情享受缓冲区的乐趣。

您可能希望将缓冲区大小加一以将空字符放入其中。

【讨论】:

  • 对于典型的 HTML 页面可以接受。但是,如果您要像这样处理大量数据转储,那您只是在浪费内存。 OP 请求是少数可以在缓冲区块上轻松实现的请求之一。
  • 问题提出(我引用)阅读所有文本文件时遇到问题。就我个人而言,我会对要阅读的大小设置上限。
  • 读取所有文本文件并不意味着整个文本文件在某个时刻存在于程序内存中。这就像阅读一本书:即使您阅读了一本书的所有内容,您也可以一页一页地阅读,但最终您会全部处理完。
  • @datenwolf - 但这不是一本书!我读到需要阅读整个文件。他在提供的代码中突出显示缓冲区大小固定,问题提到malloc
【解决方案2】:

您可以将上面的内容放在一个循环中并重复调用read() 来填充缓冲区,而不是将所有文本收集在一个缓冲区中。在阅读时处理每个块,并打印出到目前为止您已处理的部分。当您到达文件结尾时(即,当 read() 返回 0 时)停止。

【讨论】:

    【解决方案3】:

    更有效的方法是使用 mmap() 调用将文件直接映射到内存中:

    #include <sys/mman.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    
    struct stat statbuf;
    stat("data.txt", &statbuf);
    
    size_t len = stat.st_size;
    
    int fd = open("data.txt",O_RDONLY);
    
    char *buf = mmap(NULL, len, PROT_READ, MAP_PRIVATE,fd, 0);
    for( i=0; i< len; i++ ) {
       // do your own thing here
    }
    munmap(buf,len);
    close(fd);
    

    如果文件超过 2GB,则使用 mmap2() 调用 - 您将不得不调整页面大小,因为最后一个参数以页面为单位(通常为 4k)

    【讨论】:

    • 在标志参数中,您可能希望将MAP_POPULATE 包含到标志中。当你正常读取文件映射时,实际数据不在为文件分配的页面中,CPU会向内核发出中断信号以从硬盘驱动器读取。但是MAP_POPULATE会在调用时立即开始获取数据。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-24
    • 2010-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-10
    相关资源
    最近更新 更多