【问题标题】:Using read() system call使用 read() 系统调用
【发布时间】:2014-11-03 21:22:32
【问题描述】:

对于课堂作业,我们的任务是使用read() 函数读取包含数字的文件。虽然我能够将数字读入缓冲区,但我无法将它们从缓冲区移动到 char *array 中,以便可以轻松访问和排序它们。任何建议表示赞赏。

int readNumbers(int hexI, int MAX_FILENAME_LEN, int **array, char* fname) {
    int numberRead = 0, cap = 2;
    *array = (int *)malloc(cap*sizeof(int));
    int n;
    int filedesc = open(fname, O_RDONLY, 0);
    if(filedesc < 0){
        printf("%s: %s\n", "COULD NOT OPEN", fname);
        return -1;
    }
    char * buff = malloc(512);
    buff[511] = '\0';
   while(n = read(filedesc, buff+totaln, 512 - totaln) > 0) //Appears to loop only once
            totaln += n;
    int len = strlen(buff);
    for (int a = 0; a < len; a++) {  //Dynamically allocates array according to input size
        if ((&buff[a] != " ") && (&buff[a] != '\n'))
            numberRead++;
        if (numberRead >= cap){
            cap = cap*2;
            *array = (int*)realloc(*array, cap*sizeof(int));
        }
    }
    int k = 0;
    while((int *)&buff[k]){  //attempts to assign contents of buff to array
        array[k] = (int *)&buff[k];
        k++;
    }
}

【问题讨论】:

  • 为什么要将读取的数据写入 char *buff[512] 而不是单个 char * buff = malloc(MAX_FILENAME_LEN)?
  • buff 保存的是文件的内容,而不是文件名。但是,我确实将 char *buff[512] 更改为 char * buff = malloc(512)。 512是教授推荐的。

标签: c system-calls


【解决方案1】:

您对read() 的使用是错误的。至少有两个严重错误:

  1. 您忽略返回值,除非测试文件结尾。
  2. 您似乎认为read() 会在它读取的数据之后附加一个空字节。甚至可能它会用 nul 字节填充缓冲区。

如果您想在read() 返回后将更多数据读入同一个缓冲区,而不覆盖您已经读取的内容,那么您必须传递一个指向缓冲区中第一个可用 位置的指针。如果您想知道总共读取了多少字节,则需要添加返回值。通常的范例是这样的:

/*
 * Read as many bytes as possible, up to buf_size bytes, from file descriptor fd
 * into buffer buf.  Return the number of bytes read, or an error code on
 * failure.
 */
int read_full(int fd, char buf[], int buf_size) {
    int total_read = 0;
    int n_read;

    while ((n_read = read(fd, buf + total_read, buf_size - total_read)) > 0) {
        total_read += n_read;
    }

    return ((n_read < 0) ? n_read : total_read);        
}

按照这些方式做了一些事情并且没有收到错误,您可以确信read() 没有修改缓冲区中超出buf[total_read - 1] 的任何元素。它肯定没有用零填充缓冲区的其余部分。

请注意,在缓冲区满之前并不总是需要或不希望读取;示例函数出于演示目的这样做,因为它似乎是您想要的。

完成此操作后,请注意您正在尝试提取数字,就好像它们以二进制形式记录在文件中一样。情况可能确实如此,但如果您正在阅读包含 格式化 数字的 text 文件,那么您需要以不同的方式提取数字。如果这就是您所追求的,那么在读取最后一个字节后添加一个字符串终止符并使用sscanf() 来提取数字。

【讨论】:

  • 谢谢,我有点明白你在做什么,但我仍然缺少核心概念。我真的不明白存储读取的字节会有什么帮助。 numbersRead 旨在存储文件中的整数数,而不是 read() 读取的字节数。此外,我仍然没有看到如何使读入缓冲区的信息有用。虽然 printf("%s\n", buff) 显示整个文件,但我看不到将文件拆分为 int 数组的方法(这是我的最终目标)。此外,它正在读取的 .txt 文件是使用 notepad++ 制作的,并且没有字符格式。
  • read() 循环中,您需要跟踪到该点读取的总字节数,以便将 next 字节读入缓冲区的正确部分,而不是覆盖您已经阅读的内容。最后,您需要读取的总数才能知道有效数据占用了多少缓冲区。示例代码显示了如何正确执行此操作。至于从你读过的数据中提取数字,请看我回答的最后一段。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-07-11
  • 1970-01-01
  • 1970-01-01
  • 2020-11-11
  • 2014-02-22
  • 1970-01-01
  • 2021-04-27
相关资源
最近更新 更多