【问题标题】:Read N bytes from a file and print it using read() and write()从文件中读取 N 个字节并使用 read() 和 write() 打印它
【发布时间】:2018-10-24 17:54:12
【问题描述】:

我正在尝试读取一个程序,该程序使用 read() 从文件中读取 N 个字节,并使用 write() 在 STDOUT 中打印它们。问题是,用户还可以指定块大小,默认情况下它是 1024,最多只能达到 1048576。我必须将读取的内容存储在缓冲区中,但该缓冲区不能与我的字节大小相同必须阅读,否则,我可能会创建一个对于堆栈大小来说太大的缓冲区。因此,我创建了一个与块大小一样大的缓冲区,所以我只是读取直到它已满,然后写入然后再次读取到缓冲区的开头。

所有这一切的问题在于它确实无法按预期工作,我很确定必须有更简单的方法来做到这一点。

相关代码:

void run_hd_b (int b, int fd, int BSIZE){
    int res_read; //result from write
    int res_write; //result from read
    int read_bytes = 0;
    char buffer[BSIZE];
    int i = 0;

    int count = 0;
    if (b < BSIZE) count = b;
    else count = BSIZE;

    while (read_bytes < b && (res_read = read(fd, &buffer[i], count)) != 0){ 
        if (res_read == BSIZE){
            i = 0;
        }
        else i = res_read;

        read_bytes += res_read;
        while((res_write = write(1, buffer, res_read)) < res_read);
    }
}

【问题讨论】:

  • 如果您担心 VLA 导致堆栈溢出,为什么不直接 malloc 请求大小的缓冲区?
  • @Shawn 因为那样我仍然会受到堆的限制,我的程序将无法读取足够大的文件,我认为
  • 这是.. 您无法 malloc 1048576 字节的可能性极小。
  • 为什么读入&amp;buffer[i] 而不是&amp;buffer[0]
  • 缺少错误处理,这将导致在常见情况下无休止的繁忙循环((EAGAINENOSPCEPIPE,...)。write() 代码无法正常工作部分写入。在这里没关系,但数据类型错误(read()/write() 返回ssize_t,而不是int)。评论令人困惑。

标签: c linux


【解决方案1】:

下面是您的循环的修订版本,它可以编译(并且可能有效),然后是一些注释。

#include <assert.h>
#include <unistd.h>

void run_hd_n (int n, int fd, int BSIZE) {
  int res_read;
  char buffer[BSIZE];

  // can only get up to 1048576
  assert(BSIZE <= 1048576);

  for( int read_bytes=0; read_bytes < n; read_bytes += res_read ) {
    if( (res_read = read(fd, buffer, BSIZE)) < BSIZE ) { 
      if( res_read == 0 ) return; // EOF or error
    }
    if( write(STDOUT_FILENO, buffer, res_read) < res_read ) return;
  }
}
  • 我将b 更改为n 不合常规。
  • 坚持标准。 读取(2) 和写入(2) 采用size_t,而不是int。如果用n == -1 调用你的程序会有什么反应?
  • 如果您有已知的强制约束,请将其包含在某处。您声明了 BSIZE 的最大尺寸;我使用assert 来强制执行它。
  • 我不知道您的问题是关于分配空间还是复制数据。我选择解决后者。
  • 读取小于缓冲区的完整大小不是错误。无需与count 打交道。只是阅读,看看你有什么。
  • 您编写了一个返回类型为void 的I/O 函数。呼叫者将如何得知发生了什么?我会返回res_read 并让调用者测试他是否阅读了所要求的数量,否则请咨询errno

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-06-12
    • 1970-01-01
    • 2023-01-03
    • 1970-01-01
    • 2020-03-03
    • 1970-01-01
    • 2021-03-01
    • 1970-01-01
    相关资源
    最近更新 更多