0

我正在尝试 C 中的一些文件操作技术,因此我编写了一个简单的程序,它将文件作为输入并将其复制到一个空文件中。我在“二进制”和“读取”模式下使用 fopen() 打开要读取的文件,使用 fgetc() 逐个读取所有字节,并将它们写入我想要写入的文件中,该文件在“写入”和“读取”模式下打开二进制”模式。当复制操作完成(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;
}
4

3 回答 3

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;
}
于 2012-09-06T18:11:11.710 回答
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;
}
于 2012-09-06T18:31:03.913 回答
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()andfwrite()来读取和写入数据块。

#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, ...),但我没有为你解决这个问题。

于 2012-09-06T18:31:06.770 回答