简单文件复制,不同文件类型的不同行为

时间:2012-09-06 17:39:34

标签: c pdf jpeg

我在C中尝试了一些文件操作技术,因此我编写了一个简单的程序,它将文件作为输入并将其复制到空文件中。我在'二进制'和'读'模式下用fopen()打开文件读取,使用fgetc()逐个读取所有字节,并将它们写入我想写的文件,在'write'和''中打开二元'模式。当复制操作完成(EOF)时,我在两个文件上都调用了fclose()并终止了该程序。

问题在于:一切对于文本文件都非常好,但是当我尝试以不同的格式(如pdf或jpeg)复制文件时,我会遇到分段错误。由于代码非常简短,我怀疑这个问题是由于我对用C语言读取和编写这些文件格式缺乏了解而不是代码中的错误造成的。

欢迎任何建议和想法,如果您怀疑我可能对代码做错了,我也可以发布。

编辑:好的,所以我可能搞砸了代码,这里是:

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

#define MAXCHAR 10000000

int main( int argc, char** argv)
{
    if( argc != 3)
    {
        printf( "usage: fileexer1 <read_pathname> <write_pathname>");
        exit( 1);
    }

    FILE* file_read;
    FILE* file_write;

    int nextChar;
    char readBuffer[MAXCHAR];
    int valid = 0;

    // These hold the path addresses to the files to be read and written
    char* read_file_path = argv[1];
    char* write_file_path = argv[2];

    // The file to be read is opened in 'read' and 'binary' modes
    file_read = fopen( read_file_path, "rb");
    if( !file_read)
    {
        perror( "File cannot be opened for reading");
        exit( 1);
    }

    // The file to be written into is opened in 'write' and 'binary' modes
    file_write = fopen( write_file_path, "wb");
    if( !file_write)
    {
        perror( "File cannot be opened for writing");
        exit( 1);
    }

    nextChar = fgetc( file_read);
    while( nextChar != EOF)
    {
        readBuffer[valid] = (char) nextChar;
        valid++;
        nextChar = fgetc( file_read);
    }

    int i;
    for( i = 0; i < valid; i++)
    {
        fputc( readBuffer[i], file_write);
    }

    fclose( file_read);
    fclose( file_write);

   return 0;
}

3 个答案:

答案 0 :(得分:1)

我打算猜测你的代码有问题,因为编写任何二进制类型文件都没什么好看的。二进制是二进制的。这里有一些代码将名为1.jpg的图像复制到2.jpg。

int main (){
    FILE *readf, *writef;
    unsigned char *buffer;
    unsigned long len;
    int i=0;

    //Open file
    readf = fopen("1.jpg", "rb");
    writef = fopen("2.jpg","wb");

    //you should check if readf & writef were opened successfully here...

    //Get file length
    fseek(readf, 0, SEEK_END);
    len=ftell(readf);
    fseek(readf, 0, SEEK_SET);

    //Allocate memory
    buffer=(char *)malloc(len);

    //check that buffer got memory allocated here... 

    fread(buffer,fileLen,sizeof(unsigned char),readf);
    fwrite(buffer,fileLen,sizeof(unsigned char),writef);

    //cleanup
    fclose(readf);
    fclose(writef);
    free(buffer);
    return 0;
}

答案 1 :(得分:0)

如果你要逐个字符地读写,那么分配一个巨大的缓冲区来保存数据几乎没有意义。忽略错误检查:

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

   FILE *infile = fopen(argv[1], "rb");
   FILE *outfile = fopen(argv[2], "wb");

   int ch;

   while (EOF != (ch = getc(infile)))
      putc(ch, outfile);

   return 0;
}

答案 2 :(得分:0)

如果您要一次阅读一个字符,则不需要将1000万个字符保存在堆栈中的缓冲区中。并且您的代码不会优雅地处理超过1000万字节的文件。

fputc(nextChar)调用之前,只需在输入循环中使用fgetc(),并消除readBuffer变量和输出循环。如果需要,您仍然可以计算有效字符,但不需要。

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

int main( int argc, char** argv)
{
    if( argc != 3)
    {
        printf( "usage: fileexer1 <read_pathname> <write_pathname>");
        exit( 1);
    }

    FILE* file_read;
    FILE* file_write;

    int nextChar;

    // These hold the path addresses to the files to be read and written
    char* read_file_path = argv[1];
    char* write_file_path = argv[2];

    // The file to be read is opened in 'read' and 'binary' modes
    file_read = fopen( read_file_path, "rb");
    if( !file_read)
    {
        perror( "File cannot be opened for reading");
        exit( 1);
    }

    // The file to be written into is opened in 'write' and 'binary' modes
    file_write = fopen( write_file_path, "wb");
    if( !file_write)
    {
        perror( "File cannot be opened for writing");
        exit( 1);
    }

    while ((nextChar = fgetc(file_read)) != EOF)
        fputc(nextChar, file_write);

    fclose( file_read);
    fclose( file_write);

   return 0;
}

请注意,某些系统存在10 MiB堆栈的问题。如果您想提高效率,请考虑使用64 KiB缓冲区,然后使用fread()fwrite()来读取和写入数据块。

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

int main( int argc, char** argv)
{
    if( argc != 3)
    {
        printf( "usage: fileexer1 <read_pathname> <write_pathname>");
        exit( 1);
    }

    FILE *file_read;
    FILE *file_write;
    char buffer[64*1024];
    size_t nbytes;

    // The file to be read is opened in 'read' and 'binary' modes
    file_read = fopen(argv[1], "rb");
    if (!file_read)
    {
        perror("File cannot be opened for reading");
        exit(1);
    }

    // The file to be written into is opened in 'write' and 'binary' modes
    file_write = fopen(argv[2], "wb");
    if (!file_write)
    {
        perror("File cannot be opened for writing");
        exit(1);
    }

    while ((nbytes = fread(buffer, sizeof(buffer), sizeof(char), file_read)) != EOF)
    {
        if (fwrite(buffer, nbytes, sizeof(char), file_write) != nbytes)
        {
            perror("Failed to write to file");
            exit(1);
        }
    }

    fclose(file_read);
    fclose(file_write);

   return 0;
}

使用perror()会限制邮件的有效性;最好使用fprintf(stderr, ...),但我还没有解决这个问题。