【问题标题】:Writing a file to another file in .c将文件写入 .c 中的另一个文件
【发布时间】:2016-08-05 19:36:46
【问题描述】:

我有一个读取文件然后将其内容复制到另一个文件的代码。我需要让它只复制每 20 个符号,然后跳过 10 个符号,然后再跳过 20 个符号,依此类推。

我必须使用 lseek() 函数,但我不知道如何将所有这些都放入循环中来完成它。

main (argc, argv)
int argc;
char *argv[];
{
    int fd1, fd2;
    int nbytes, mode;
    char buf[BUFSIZ];
    if(argc<3){
        fprintf(stderr, "%s: nepareizs kopesanas parametrs\n", argv[0]);
        exit(1);
    }
    if((fd1 = open(argv[1], O_RDONLY)) < 0){
        fprintf(stderr, "Nevar atvert failu %s\n", argv[1]);
        exit(1);
    }
    if((fd2 = open(argv[2], O_WRONLY | O_CREAT, mode))<0){
        fprintf(stderr, "Nevar izveidot jaunu failu %s\n", argv[2]);
        exit(1);
    }

    nbytes = lseek(fd1, 10, 0)
    while((nbytes = read(fd1, buf, BUFSIZ))>0){
            if(write(fd2, buf, nbytes) < 0){
                fprintf(stderr, "не понимаю\n");
                break;

            }

    }

    if (nbytes<0)
        fprintf(stderr, "не понимаю\n");
    close(fd1);
    close(fd2);
    exit(0);
}

【问题讨论】:

  • 读入 30 个字节的块,但只使用前 20 个。
  • 你为什么使用老式的 C 语言?
  • 因为我的老师很古老。他一直在红军中为苏联而战。大声笑。
  • lseek(fd1, 10, 0) 中的幻数很可疑。使用适当的宏。
  • @MartinJames,最糟糕的是,他为自己在战争中的成就感到非常自豪。他给我们讲了一半关于战争和教操作系统的老俄罗斯书籍的讲座。他真的不是在教书,只是告诉我们必须用这些功能做什么,仅此而已。

标签: c linux file


【解决方案1】:

替换

nbytes = lseek(fd1, 10, 0)
while((nbytes = read(fd1, buf, BUFSIZ))>0){
        if(write(fd2, buf, nbytes) < 0){
            fprintf(stderr, "не понимаю\n");
            break;

        }

}

while((nbytes = read(fd1, buf, BUFSIZ))>0){
        /* first you write your 20 bytes */
        if(write(fd2, buf, nbytes) < 0){
            fprintf(stderr, "не понимаю\n");
            break;

        }
        /* and then you move 10 bytes further */
        if (lseek(fd1, 10, 0) < 0){
            /* break if this is the eof */
            break;
        }

}

如果 BUFSIZ 为 20。

或者,最简单的,BUFSIZ = 30:

while((nbytes = read(fd1, buf, BUFSIZ))>0){
    /* you only write the first 20 read bytes, or nbytes
       if there are no much bytes in the buffer */
    if(write(fd2, buf, nbytes < 20 ? nbytes : 20) < 0){
        fprintf(stderr, "не понимаю\n");
        break;
    }
}

【讨论】:

  • 为什么不创建BUFSIZ 30WRTSZ 20,删除整个第二个if 块和write(fd2, buf, WRTSZ)?似乎是更简单的解决方案,并且完全避免了 lseek 调用?
  • 他想用seek,但确实如此,它一定是更好的解决方案。我会写的。
【解决方案2】:

要考虑的其他替代方案。您的问题的 cmets 中提到了许多优点。下面的示例收集了各种 cmets,并提供了一种读取 30 字节并将前 20 字节写入输出文件的简洁方法。

避免使用所有幻数(在整个代码中散布的硬编码值)。读取和写入都经过验证,使用流操作(例如freadfwrite)而不是readwrite)并验证输出文件的close

#include <stdio.h>

enum { WRTSZ = 20, BUFSZ = 30 };

int main (int argc, char **argv) {

    if (argc < 3 ) {
        fprintf (stderr, "error: insufficient input, usage: %s ifile ofile\n",
                argv[0]);
        return 1;
    }

    FILE *ifp = fopen (argv[1], "rb");
    FILE *ofp = fopen (argv[2], "w+");
    char buf[BUFSZ] = "";

    if (!ifp) { /* validate file open for reading (binary) */
        fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
        return 1;
    }
    if (!ofp) { /* valdate file open for writing */
        fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
        return 1;
    }
    /* read BUFSZ bytes (require at least WRTSZ), and output */
    while (fread (buf, sizeof *buf, BUFSZ, ifp) >= WRTSZ)
        if (fwrite (buf, sizeof *buf, WRTSZ, ofp) != WRTSZ)
            fprintf (stderr, "error: fwrite of WRTSZ failed.\n");

    fclose (ifp);
    if (fclose (ofp))   /* validate close of output file */
        fprintf (stderr, "error: on close of '%s'.\n", argv[2]); 

    return 0;
}

(注意:只写入 20 字节的完整块。如果最后一次读取是小于 20 字节的部分读取,则该信息不会写入输出文件。您可以调整 freadfwrite 周围的条件以根据您的需要调整行为。)

示例输入文件(非 POSIX,无 eol)

以下输入文件是用于示例目的的文本,它不包含 POSIX end-of-line ('\n')。 (如果您愿意,可以包含换行符,它只会导致将换行符写入输出文件)

$ cat dat/ruler.txt
........10........20........30........40........50........60........70........80........90

使用/输出文件

$ ./bin/rd30wrt20 dat/ruler.txt dat/rulerout.txt
$ cat dat/rulerout.txt
........10........20........40........50........70........80

查看一下,如果您有任何问题,请告诉我。

写入所有字节(0

如果您想写入在上次fread 期间读取的任何部分字节,您可以将条件调整为类似于以下内容:

size_t rdsz;
...
/* read BUFSZ bytes, write 0 < rdsz <= WRTSZ */
while ((rdsz = fread (buf, sizeof *buf, BUFSZ, ifp)))
    if (fwrite (buf, sizeof *buf,
        rdsz > WRTSZ ? WRTSZ : rdsz, ofp) != WRTSZ)
        fprintf (stderr, "warning: fwrite of '%zu'.\n", rdsz);

【讨论】:

    猜你喜欢
    • 2015-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-24
    • 2017-04-27
    • 1970-01-01
    相关资源
    最近更新 更多