低级别的CI/O:当从一个文件读取并写入另一个我正在打一个无限循环

问题描述:

我正在处理一个只允许使用低级别I/O(读(),写( ),lseek())以及perror()。低级别的CI/O:当从一个文件读取并写入另一个我正在打一个无限循环

我已经能够打开具有正确权限的输入输出文件,但是当我输出时,我得到了文件内容的无限循环输出。请参见下面的一段:

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

我已删除了一些错误从我的代码捕获,你可以假设变量初始化,包括声明在那里。

+0

到目前为止,您已经完成了哪些调试?例如,哪个循环被卡住,外部循环还是内部循环? – 2012-03-19 00:38:55

+1

我认为你在做的是重复写同一行。尝试将'write'周围的'while'改为'if' – twain249 2012-03-19 00:41:33

+0

它卡在内部循环中。除此之外,我不能告诉你其他的事情。 – Dan 2012-03-19 00:43:12

问题是内部循环:

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

确实应该

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

你只想buf被写入一次,而不是无限多次。你还需要处理很短写,也就是,当有m个写入返回<ň& & M> 0

此外,lseek()电话是错的,但它们不会导致循环。 read()write()已经提前当前的文件偏移量。除非要跳过输入或输出文件中的字节(注意在输出文件的情况下,在UNIX上,跳过字节可能会导致文件中出现所谓的“漏洞”,这些区域是零但不占用磁盘空间)。

为什么你在阅读后寻找输入文件?由于您最多可以读取1024个字节(意思是n将介于0到1024之间),您将继续寻找超出您已经离开输入文件指针的地方,以便您将丢失中的数据转移(包括在您接近结束时可能超出文件末尾)。

可能是一个原因,为什么你有一个无限循环,但更为阴险的是使用while写入。由于这将在成功时返回大于零的值,因此您将不断将第一个块重复写入文件。至少在您耗尽磁盘空间或其他资源之前。

您也不需要写入seekreadwrite呼叫做他们必须做的为下一个readwrite正确地提前文件指针 - 这不是你必须手动完成的。

你也许可以简化整个事情:

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

它的优点是:

  • 摆脱seek通话;
  • 删除'无限'循环;
  • 检查您是否写过全部请求的字节数。
+2

考虑到SEEK_CUR的哪个值,会不会将文件中的当前位置增加n? – Dan 2012-03-19 00:41:29

+1

准确地说,这就是lseek()调用不会导致循环的原因,它们只会导致跳过的字节。 – 2012-03-19 00:44:29