将一个文件复制到另一个文件(Unix / C)?

时间:2016-01-31 21:49:54

标签: c unix cp file-copying

我编写了以下代码将一个文件复制到另一个文件。虽然代码有效,但代码仍会打印错误消息。为什么是这样 ?我是Unix和C编程的完全初学者(虽然之前我曾使用过C ++),所以尽可能详细的任何帮助都会很棒。谢谢!

int main(int argc, char *argv[])
{
    int n;
    char buf[4096];
    while ((n=read( open(argv[1], O_RDONLY) , buf, 4096))>0)
    {
        if (write(creat(argv[2], S_IREAD | S_IWRITE ), buf, n)!=n)
            printf("Error writing to file.\n");
    }
    if (n<0)
        printf("Error reading from file.\n");
    exit(0);
}

2 个答案:

答案 0 :(得分:3)

您在每次迭代中打开文件,并在每次迭代中尝试creat该文件。

因此,除了第一次迭代之外,所有后续写入都将失败。它可能&#34;似乎工作&#34;因为您的输入文件包含少于4096个字节。因此,第一次写入是让它看起来像是复制了所有东西。 如果使用超过4096字节的输入,则只会看到前4096个字节(假设read()write()都不会失败)。

如果write()一直在成功(例如你在循环之外有creat())那么open()调用会持续打开同一个文件,并且可能是无限循环或你的系统将耗尽文件描述符并返回无效的文件描述符,read()将失败。

长话短说:不要写这样的代码:)

将两次调用移至循环外的open()creat()

int fd = open(argv[1], O_RDONLY);
if (fd == -1) { 
   perror("open");
   exit(1);
}

int fd2 = creat(argv[2], S_IREAD | S_IWRITE );
if (fd2 == -1) { 
   perror("write");
   exit(1);
}

while ( (n=read( fd , buf, 4096)) > 0 )
{
    if ( write(fd2 , buf, n) != n )
        printf("Error writing to file.\n");
}

答案 1 :(得分:2)

上面的答案已经发现,但是应该避免使用creat(),因为create()是一个过时的函数。 create(filename,mode);相当于 open(filename,O_WRONLY | O_CREAT | O_TRUNC,mode);

http://www.gnu.org/software/libc/manual/html_node/Opening-and-Closing-Files.html

代码可以写得更好:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

#define BUFSIZE 4096

int main(int argc, char **argv)
{
    int infd, outfd;
    int n;
    char *infile = NULL;
    char *outfile = NULL;
    int src_flags, dest_flags;
    mode_t dest_perms;
    char buf[BUFSIZE];

    if (argc < 3) {
        fprintf(stderr, "At least src and dest files must be specified\n"); /*Never rely on users' inputs*/
        /*Print usage information if possible*/
        exit(EXIT_FAILURE); 
    }

    infile = argv[1];
    outfile = argv[2];  /*Presuming the order*/            

    src_flags = O_RDONLY;
    dest_flags = O_CREAT | O_WRONLY | O_TRUNC;  
    /*creat() is equivalent to open(fname, O_CREAT | O_WRONLY | O_TRUNC, mode)*/
    dest_perms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; /*rw-rw-rw-*/

    infd = open(infile, src_flags);
    if (infd == -1) {
        perror("cannot open src ");
        exit(EXIT_FAILURE);
    }

    outfd = open(outfile, dest_flags, dest_perms);
    if (outfd == -1) {
        perror("cannot open dest ");
        exit(EXIT_FAILURE);
    }

    while ((n = read(infd, buf, BUFSIZE)) > 0) {
        if (write(outfd, buf, n) != n) {
            fprintf(stderr, "failed to write buf\n");
            goto exit_failure;
        }
    }

    if (n == -1) {
        fprintf(stderr, "read() failed\n");
        goto exit_failure;
    }

exit_failure:
     if (infd) {
        close(infd);
     }

    if (outfd) {
        close(outfd);
    }

    printf("Copy successful\n");

    exit(EXIT_SUCCESS);
}