linux 在C中将内容从一个文件复制到另一个文件

chhkpiq4  于 2022-11-28  发布在  Linux
关注(0)|答案(3)|浏览(286)

给定一个txt文件,我试图制作一个C程序,把它的内容复制到另一个文件中,这个文件的名字是通过参数传递的。程序必须从源文件中读取512字节的块,并把读取的字节写入目标文件。
我的尝试:

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

int main(int argc, char* argv[]){
    if(argc < 2){
        printf("ERROR: Missing arguments\n");
        exit(1);    
    }

    int fdo, fdd;

    if((fdo = open(argv[1], O_RDONLY)) == -1){
        printf("ERROR: Origin file %s can not be opened\n", argv[1]);
        exit(1);
    }

    if(fdd = open(argv[2], O_CREAT | O_TRUNC, 0666) == -1){
        printf("ERROR: Dest. file %s can not be opened\n", argv[2]);
        exit(1);
    } 

    char buff[512];
    size_t n_bytes;

    while((n_bytes = read(fdo,buff,512)) > 0){
        if(write(fdd,buff,n_bytes) < 0){
            printf("Can not write buffer content in %s \n", argv[2]);
            exit(1);
        }
    }

    if(n_bytes < 0){
        printf("Can not read %s file \n", argv[1]);
        exit(1);
    }

    close(fdo);
    close(fdd);

    return 0;
}

test.txt文件的内容为:

abcdef
1890

其权限为:

usuarioso@usuarioso-virtualbox:~/Documentos/SO 2022/pr2/API de ficheros y directorios$ ls -l
total 32
-rwxrwxr-x 1 usuarioso usuarioso 17048 nov 23 16:15 copyrf
-rw-rw-r-- 1 usuarioso usuarioso   774 nov 23 16:39 copyrf.c
-rw-rw-r-- 1 usuarioso usuarioso    12 nov 23 16:52 test.txt

然而,当我执行它时,我得到以下结果:

usuarioso@usuarioso-virtualbox:~/Documentos/SO 2022/pr2/API de ficheros y directorios$ gcc -o copyrf copyrf.c
usuarioso@usuarioso-virtualbox:~/Documentos/SO 2022/pr2/API de ficheros y directorios$ ./copyrf test.txt test1.txt
abcdef
1890
usuarioso@usuarioso-virtualbox:~/Documentos/SO 2022/pr2/API de ficheros y directorios$ ls -l
total 28
-rwxrwxr-x 1 usuarioso usuarioso 17008 nov 23 17:00 copyrf
-rw-rw-r-- 1 usuarioso usuarioso   771 nov 23 16:59 copyrf.c
-rw-rw-rw- 1 usuarioso usuarioso     0 nov 23 17:00 test1.txt
-rw-rw-r-- 1 usuarioso usuarioso    12 nov 23 16:52 test.txt
usuarioso@usuarioso-virtualbox:~/Documentos/SO 2022/pr2/API de ficheros y directorios$ cat test1.txt
usuarioso@usuarioso-virtualbox:~/Documentos/SO 2022/pr2/API de ficheros y directorios$

即创建了文件test1.txt,但该文件为空,并且在控制台中打印了文件test.txt的内容。
我错过了什么?

7hiiyaii

7hiiyaii1#

Clang的gcc很好地指出了这个问题:

$ gcc temp.c
temp.c:19:12: warning: using the result of an assignment as a condition without parentheses [-Wparentheses]
    if(fdd = open(argv[2], O_CREAT | O_TRUNC, 0666) == -1){
       ~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
temp.c:19:12: note: place parentheses around the assignment to silence this warning
    if(fdd = open(argv[2], O_CREAT | O_TRUNC, 0666) == -1){
           ^
       (                                                 )
temp.c:19:12: note: use '==' to turn this assignment into an equality comparison
    if(fdd = open(argv[2], O_CREAT | O_TRUNC, 0666) == -1){
       ^
           ==

...特别地,fdd被设置为(open(...) == -1)的结果,即如果open()调用返回-1,则设置为1,或者如果open()调用返回任何其它值,则设置为0。由于01都不是open()返回的文件描述符的值,对write(fdd, ...)的后续调用使用了无效的文件描述符值,因此失败。
修复方法是像第一次调用/open-for-read open()时那样添加括号,使其如下所示:

if((fdd = open(argv[2], O_CREAT | O_TRUNC, 0666)) == -1){

除此之外,还需要将O_WRONLY添加到第二次调用open()oflag参数中,否则将不允许fdd写入文件。

fykwrbwg

fykwrbwg2#

您忘记了一些括号,因此fdd被设置为0或1,而不是open的返回值。将其与fdo代码进行比较。最好避免在表达式中进行赋值,除非您确实知道自己在做什么。这也是在简化代码时首先要删除的内容之一,以便为堆栈溢出创建一个最小的完整可验证示例。

b5lpy0ml

b5lpy0ml3#

行中:

if((fdo = open(argv[1], O_RDONLY)) == -1)

你把赋值放在括号里。这首先把打开的文件描述符赋值给fdo,然后检查该值是否等于-1。
另一方面,在第二种情况下:

if(fdd = open(argv[2], O_CREAT | O_TRUNC, 0666) == -1)

您没有将赋值放在方括号中。因此,首先计算==运算符,它返回值0(假)或1(真),而不是有效的文件描述符。然后将此值赋给fdd,导致您写入错误的文件描述符(标准输出)。

相关问题