C 简单的文件复制,在不同的文件类型上有不同的行为
我尝试了一些C语言中的文件操作技术,所以我编写了一个简单的程序,将一个文件作为输入并复制到一个空文件中。我在“二进制”和“读取”模式下用fopen()打开了要读取的文件,使用fgetc()逐个读取所有字节,并将它们写入我想要写入的文件,该文件在“写入”和“二进制”模式下打开。当复制操作完成(EOF)时,我对这两个文件调用了fclose()并终止了程序 问题是:对于文本文件来说,一切都很好,但是当我尝试以不同的格式复制文件(如pdf或jpeg)时,我会遇到分割错误。由于代码非常简短,我怀疑这个问题是因为我对用C语言读写这些文件格式缺乏理解,而不是因为代码中有错误 欢迎您提出任何建议和想法,如果您怀疑我可能对代码做了一些错误,我也可以发布它 编辑:好的,我可能把代码搞乱了,现在是:C 简单的文件复制,在不同的文件类型上有不同的行为,c,pdf,jpeg,C,Pdf,Jpeg,我尝试了一些C语言中的文件操作技术,所以我编写了一个简单的程序,将一个文件作为输入并复制到一个空文件中。我在“二进制”和“读取”模式下用fopen()打开了要读取的文件,使用fgetc()逐个读取所有字节,并将它们写入我想要写入的文件,该文件在“写入”和“二进制”模式下打开。当复制操作完成(EOF)时,我对这两个文件调用了fclose()并终止了程序 问题是:对于文本文件来说,一切都很好,但是当我尝试以不同的格式复制文件(如pdf或jpeg)时,我会遇到分割错误。由于代码非常简短,我怀疑这个问题
#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;
}
#包括
#包括
#定义MAXCHAR 10000000
int main(int argc,字符**argv)
{
如果(argc!=3)
{
printf(“用法:fileexer1”);
出口(1);
}
文件*文件读取;
文件*文件写入;
int nextChar;
char readBuffer[MAXCHAR];
int valid=0;
//它们保存要读取和写入的文件的路径地址
char*read_file_path=argv[1];
char*write_file_path=argv[2];
//要读取的文件以“读取”和“二进制”模式打开
file_read=fopen(读取文件路径,“rb”);
如果(!文件读取)
{
perror(“文件无法打开读取”);
出口(1);
}
//要写入的文件以“写入”和“二进制”模式打开
file_write=fopen(写入文件路径,“wb”);
如果(!文件写入)
{
perror(“无法打开文件进行写入”);
出口(1);
}
nextChar=fgetc(文件读取);
while(nextChar!=EOF)
{
readBuffer[valid]=(char)nextChar;
有效++;
nextChar=fgetc(文件读取);
}
int i;
对于(i=0;i
我敢打赌,你的代码一定有问题,因为写二进制类型的文件没有什么特别的地方。二进制就是二进制。下面是一些将名为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;
}
如果你打算一个字符一个字符地读写,那么分配一个巨大的缓冲区来保存数据就没有什么意义了。忽略错误检查:
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;
}
如果要一次读取一个字符,则不需要在堆栈的缓冲区中保存1000万个字符。而且您的代码无法正常处理超过1000万字节的文件 只需在调用
fgetc()
之前的输入循环中使用fputc(nextChar)
,并消除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;
}
使用
peror()
会限制您的消息的有用性;最好使用fprintf(stderr,…)
,但我还没有为您解决这个问题。当然,C对文件格式一无所知,所以您的代码中一定有错误。是的,我知道一次读取一个字符效率不高,我只是在试验,但我尝试的一些文件小于10MB,你认为代码中可能存在另一个错误而不是冗余吗?@john27:实际上,使用getc/putc并不是那么低效——在幕后,库会为你做缓冲,所以你一次读取更大的块(例如4Kib)。不确定它是你当前问题的根源,但是你可能想考虑如果你试图复制一个大于<代码> Max Char < /C> >的文件会发生什么……嗯,我只是抛弃了Jerry Coffin所说的使用缓冲区的全部想法。它成功了。虽然我没有在大于10MiB的文件中得到分段错误,但是在一些大约7MiB的文件中得到了分段错误,我猜缓冲区是错误背后的原因。
#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;
}