这是一个用于创建文件或目录副本的c代码,在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);
}
答案 0 :(得分: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))) );
}
外部循环确保您阅读,直到没有任何内容可供阅读,内部同时确保您致电write
,直到written
与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);
}
}
}
}