1

这是创建文件或目录副本的 ac 代码,在 fedora 19 中使用 gcc 编译。它运行但不会停止,我可以看到创建的新文件的大小不断增加,可笑。这段代码有什么问题?

#include<fcntl.h>
#include<stdio.h>
#include<unistd.h>

char buffer[2048];

int version = 1;

int main(int argc, char *argv[])
{
    void copy (int, int);

    int fdold, fdnew;

    if (argc != 3)
    {
        printf("insufficient arguments !!! \n");
        return (1);
    }

    fdold = open(argv[1], O_RDONLY);
    if (fdold == -1)
    {
        printf("cannot open file %s\n",argv[1]);
        return (1);
    }

    fdnew = creat(argv[2],0666);
    if (fdnew == -1)
    {
        printf("cannot create file %s\n",argv[2]);
        return (1);
    }

    copy (fdold, fdnew)

    return (0);
}

void copy (int fdold, int fdnew)
{
    int count;
    count = read(fdold, buffer, sizeof(buffer));

    while (count > 0)
        write(fdnew, buffer, count);
}
4

1 回答 1

5

您永远不会更新count,并且一遍又一遍地写入相同的数据。在这段代码中:

count = read(fdold, buffer, sizeof(buffer));
while (count > 0)
    write(fdnew, buffer, count);

您从文件描述符中读取一次,拉入count字节,虽然它大于0(可能是),但您继续将缓冲区写入新文件。您再也不会从旧文件中读取任何数据。如果您可以看到文件越来越大,您可能还可以看到(取决于内容如何刷新到磁盘)一遍又一遍地重复相同的内容。

你实际上需要做的是更像这样的事情:

while there is data to read from the old file
  read it into a buffer
  while there is data in the buffer to write to the new file
    write data from the buffer into the new file

以稍微不那么伪代码但高度未经测试的形式,我认为你会寻找类似这样的东西:

int count = 0;
int written;
while ( 0 < (count = read(fdold, buffer, sizeof(buffer))) ) {
  written = 0;
  while ( count > (written += write(fdnew, buffer+written, count-written))) );
}

外层循环确保你一直读到没有东西要读,内层 while 确保你调用writeuntilwritten和 一样大count,也就是说,直到你写完你读到的所有字节。这是“聪明”的代码,但实际上太聪明了;你实际上需要检查是否written-1,否则你会开始做一些奇怪的事情。

具有更多错误检查并且希望更惯用的东西可能是:

  for ( int count_in = -1; count_in != 0; ) {
    if ( -1 == (count_in = read(fd, buf, bufsize))) {
      perror("Problem reading from file");
      exit(-1);
    }
    else { 
      for ( int count_out = 0, out = 0; count_out < count_in; count_out += out ) {
        if ( -1 == (out = write(fd, buf+count_out, count_in-count_out)) ) {
          perror("Problem writing to file");
          exit(-1);
        }
      }
    }
  }
于 2013-10-18T04:07:22.087 回答