0

好的,我有一个家庭作业,使用 POSIX API 在 C 中编写一个文件,该 API 要求读取一个文件名,一个要写入的文件名,然后将一个文件复制到另一个文件名。我已经这样做了,效果很好!我正在尝试进行一些错误检查,我想检查要写入的文件是否已经存在,如果存在,然后询问用户是否希望覆盖。问题是它总是声明文件存在,即使它不存在。该程序的其余部分工作得很好。我在这里阅读了很多内容,并在 POSIX 上找到了很多有用的东西,但找不到此类问题可供参考。下面是我的代码:

#include <fcntl.h>   // POSIX: give access to open
#include <unistd.h>  // POSIX: gives access to read, write, close
#include <stdio.h>   // POSIX: gives access to BUFSIZ

int main() {

int source = -1;
int target;
char sourcefile[50];
char targetfile[50];
char buff[BUFSIZ];
char ow[3];
size_t size;

printf("Please enter the name of the file you wish to read: ");
scanf( "%s", sourcefile );
printf( "\n" );
printf("Please enter the name of the file you wish to write to: ");
scanf( "%s", targetfile );
printf( "\n" );

source = open( sourcefile, O_RDONLY, 0);
//Test for existence of input file
if( source == -1 )
{
    perror( "Cannot find file" );
    return 1;
}
target = open( targetfile, O_WRONLY, 0644 );
//Test for existence of output file
if( target == 0 )
{
    perror( "File already exists" );
    printf( "Do you wish to overwrite? (yes or no): " );
    scanf( "%s", ow );

    if( strcmp( ow, "yes" ) == 0 )
    {
        target = open( targetfile, O_WRONLY | O_CREAT, 0644);   
    }else
    {
        printf( "Program Terminated!\n" );
        return 1;   
    }   
}else if( target == -1 )
{
    target = open( targetfile, O_WRONLY | O_CREAT, 0644);
}

while ((size = read(source, buff, BUFSIZ)) > 0) 
{
    write(target, buff, size);
}

close(source);
close(target);

return 0;
}
4

1 回答 1

3

您可以使用open(2)withO_EXCL创建声称的新文件。如果文件已经存在,这将失败;在那种情况下会致命地中止。否则,您可以将所需的文件内容写入其中。

如果你想成为原子的,你可以将文件内容写入一个临时文件(使用tmpfile),然后用原子替换创建的文件rename(2)。这样,新文件要么是空的,要么是完整的副本。


另一种选择(由@R. 建议)是不打扰打开目标文件,复制到临时文件中,然后使用link(2)而不是rename尝试将新文件放在其目标位置。如果目的地已经存在,这将失败。这可能具有(有争议的)好处,如果其他人同时创建目标文件并且没有像我们一样小心谨慎,那么在这种情况下你会更温和一些。(但如果其他人想在你的文件系统周围不小心踩踏,你能做的就这么多了。)

于 2013-01-29T00:47:21.863 回答