如何在C程序中使用“ BUFSIZ”将整个文件复制或写入另一个文件?

时间:2019-07-06 20:55:17

标签: c file-io

尝试使用C的BUFSIZ读取文件并写入另一个新文件。但是阅读循环会无限进行。问题在哪里以及如何解决。

[cpy.c]
// Copy from file 1 to file 2

#include <stdio.h>
#include <stdlib.h> // For 'exit'
#include <stdarg.h> // For va_args

#include "unistd.h" // For 'open'  (for Windows Only)
#include <fcntl.h>  // For 'O_RDONLY'

#define PERMS 0666

void error(char *, ...);

long getFileSize(char *);

int main(int argc, char *argv[])
{
    ssize_t n;
    int f1, f2;
    char buf[BUFSIZ];

    long writtenBytes = 0;
    float toMb = 1024 * 1024;
    float percent;

    if (argc < 3) {
        error("Usage: cpy <from.ext> <to.ext>");
    }

    // Opening source file.
    if ((f1 = open(argv[1], O_RDONLY, 0)) == -1)
        error("Unable to read a %s file.", argv[1]);

    long fileSize = getFileSize(argv[1]); // in Bytes
    float fileSizeMb = fileSize / toMb;
    printf("Source file (Size: %.2f Mb): %s\n", fileSizeMb, argv[1]);

    // Create a Destination file
    if ((f2 = creat(argv[2], PERMS)) == -1)
        error("Unable to create a destination file (%s).", argv[2]);

    // Read a source file.
    while ((n = read(f1, buf, BUFSIZ)) != -1) // > 0 // **TO FIX #1** 
        if (write(f2, buf, n) != n)
            error("While writing data to (%s) file! Please try again.", argv[2]);
        else {
            //printf("\r%d Bytes are readed now.", n);
            writtenBytes += BUFSIZ; //(long) n;  // **TO FIX #2** 

            percent = (float) writtenBytes / fileSize;
            printf("\r%.2f%% (%.2f / %.2f Mb) is completed", percent, writtenBytes/(toMb*100.0), fileSizeMb);
            //fflush(stdout);
        }

    printf("\nFile (%s) is copied.", argv[2]);
    return 0;
}

// Get The size of the file.
long getFileSize(char *filepath)
{
    FILE *fh = fopen(filepath, "r");

    if (fh == NULL) {
        error("FILESIZE: Unable to open a \"%s\" file.\n", filepath);
        return 0;
    }

    // Go to end of the file.
    fseek(fh, 0, SEEK_END);
    long filesize = ftell(fh);
    // Set back seek to beginning of the file, for next time read.
    fseek(fh, 0, SEEK_SET);
    return filesize;
}

// Print an Error msg and die
void error(char *fmt, ...)
{
    va_list args;

    va_start(args, fmt);
    fprintf(stderr, "Error: ");
    vfprintf(stderr, fmt, args);
    fprintf(stderr, "\n");
    va_end(args);

    exit(1);
}

目标是将其读取并写入新文件,并显示完成的“百分比”以及此时已写入的字节。

猜测,要修复的行在代码内部标记为'** TO FIX ##'**。

  • 代码“ TO FIX#1”-使用'> 0'时,实际上并没有编写任何内容。
  • 代码“ TO FIX#2”-我认为它应该是'n'而不是 为了获得确切的字节,必须在最后写入“ BUFSIZ” 完成。

最后,在“ Ctrl + C”之后,文件的“ 90 Mb”总是只写入“ 11 KB”。

编译:{{1​​}}

运行:cpy从.mp4到.mp4

Env:代码块17.12,Windows 10 64位

谢谢。

1 个答案:

答案 0 :(得分:0)

read(2)命中文件末尾时,它returns 0,而不是-1。

您的代码到达文件末尾,并且read从那一刻起返回0,但是您只会在-1处停止。