2

我正在处理一项只允许使用低级 I/O(read()、write()、lseek())以及 perror() 的任务。

我已经能够以正确的权限打开 nessisary in 和 out 文件,但是当我输出时,我得到了 in 文件内容的无限循环。请参阅下面的片段...

void *buf = malloc(1024);
while((n = read(in, buf, 1024)) > 0){
    if(lseek(in, n, SEEK_CUR) == -1){
        perror("in file not seekable");
        exit(-1);
    }
    while((m = write(out, buf, n)) > 0){
        if(lseek(out, m, SEEK_CUR) == -1){
            perror("out file not seekable");
            exit(-1);
        }
    }
    if(m == -1){ perror("error writing out"); exit(-1); }
}
if(n == -1){ perror("error reading in"); exit(-1); }

我已经从我的代码中删除了一些错误捕获,您可以假设变量已初始化并且包含语句在那里。

4

2 回答 2

2

问题是内部循环:

while((m = write(out, buf, n)) > 0){

真的应该

if((m = write(out, buf, n)) > 0){

你只想buf被写一次,而不是无限多次。您还需要处理的是短写入,即当 write 返回时 m < n && m > 0。

此外,lseek()调用是错误的,但它们不会导致循环。read()并且write()已经提前了当前文件偏移量。您不需要手动推进它,除非您想跳过输入或输出文件中的字节(请注意,在输出文件的情况下,在 UNIX 上,跳过字节可能会导致文件中出现所谓的“漏洞”,即零但不占用磁盘空间)。

于 2012-03-19T00:41:14.163 回答
0

为什么在阅读后寻找输入文件?由于您最多会读取 1024 个字节(意思n是介于 0 和 1024 之间),因此您将不断寻找超出输入文件指针的位置,以便在传输过程中丢失数据(包括当您接近结尾时,可能会超出文件的结尾)。

可能是导致无限循环的原因之一,但更阴险的是使用whilefor write。由于这将在成功时返回大于零的值,因此您将不断地将第一个块不断地写入文件。至少在您用完磁盘空间或其他资源之前。

您也不需要seekon the write 。readandwrite调用完成了它们必须做的事情,为下一个正确地推进文件指针,read或者write- 这不是您必须手动执行的操作。

您可能可以将整个事情简化为:

while ((n = read (in, buf, 1024)) > 0) {
    if ((m = write (out, buf, n)) != n) {
        perror ("error writing out");
        exit (-1);
    }
}

它具有以下优点:

  • 摆脱seek电话;
  • 删除“无限”循环;
  • 检查您是否已写入请求的所有字节。
于 2012-03-19T00:38:40.070 回答