c语言中的复制实用程序(如*NIX中的cp),无法复制mp4或mp3文件
我试图通过使用管道在C中创建一个复制实用程序,就像*NIX中的c语言中的复制实用程序(如*NIX中的cp),无法复制mp4或mp3文件,c,linux,unix,C,Linux,Unix,我试图通过使用管道在C中创建一个复制实用程序,就像*NIX中的cp一样 该代码适用于txt文件,但当我复制mp4或mp3文件时,它们会损坏。 对于mp4文件,我得到未选择视频或音频,对于mp3文件,我得到无法识别文件格式 我正在分配250字节的缓冲区,并分别向管道和从管道向文件(源文件和目标文件)读写250字节。文件的路径假定通过命令行参数给定 如果我读写要复制的文件的完整大小,从管道到管道,代码工作正常。但当我使用250字节的缓冲区时,它不起作用 我无法将文件大小分配给buff和childbu
cp
一样
该代码适用于txt文件,但当我复制mp4或mp3文件时,它们会损坏。
对于mp4文件,我得到未选择视频或音频
,对于mp3文件,我得到无法识别文件格式
我正在分配250字节的缓冲区,并分别向管道和从管道向文件(源文件和目标文件)读写250字节。文件的路径假定通过命令行参数给定
如果我读写要复制的文件的完整大小,从管道到管道,代码工作正常。但当我使用250字节的缓冲区时,它不起作用
我无法将文件大小分配给buff
和childbuff
,因为这样我将无法复制大小大于RAM(即8GB)的文件
谢谢你的帮助
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
int main(int argc, char **argv) {
int fildes[2];
char ch;
int bytes, target, handle;
pid_t cpid;
int sz = 0;
struct stat st;
stat(argv[1], & st);
sz = st.st_size;
char * buff = malloc(250);
char * childbuff = malloc(250);
pipe(fildes);
if (argc != 3) {
printf("Command needs two arguments");
exit(1);
}
if (access(argv[1], F_OK) == -1) {
printf("File %s , not found", argv[1]);
exit(0);
}
if (access(argv[2], F_OK) != -1) {
printf("File already exists, Do you want to overwrite ? [y,n]");
scanf("%c", & ch);
if (ch == 'n') {
exit(0);
}
FILE * fil = fopen(argv[2], "wb");
fclose(fil);
}
int tmp = 250, tmp1 = 250, wr = 0, rr = 0;
cpid = fork();
if (cpid == -1) {
perror("fork");
exit(1);
}
if (cpid == 0) {
FILE * ptr = fopen(argv[2], "wb");
while (rr < sz) {
if (sz - rr < 250)
tmp1 = sz - rr;
else
tmp1 = 250;
rr = rr + tmp1;
close(fildes[1]);
read(fildes[0], childbuff, tmp1);
close(fildes[0]);
fwrite(childbuff, 1, tmp1, ptr);
}
fclose(ptr);
} else {
FILE * ptr = fopen(argv[1], "rb");
while (wr < sz) {
if (sz - wr < 250)
tmp = sz - wr;
else
tmp = 250;
wr = wr + tmp;
close(fildes[0]);
bytes = fread(buff, 1, tmp, ptr);
write(fildes[1], buff, bytes);
}
fclose(ptr);
}
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int main(int argc,字符**argv){
int fildes[2];
char ch;
int字节,目标,句柄;
pid_t cpid;
int sz=0;
结构统计;
统计(argv[1],&st);
sz=标准尺寸;
char*buff=malloc(250);
char*childbuff=malloc(250);
管道(菲尔德斯);
如果(argc!=3){
printf(“命令需要两个参数”);
出口(1);
}
if(访问(argv[1],F_OK)=-1){
printf(“文件%s,未找到”,argv[1]);
出口(0);
}
如果(访问(argv[2],F_确定)!=-1){
printf(“文件已存在,是否覆盖?[y,n]”);
scanf(“%c”和“ch”);
如果(ch='n'){
出口(0);
}
文件*fil=fopen(argv[2],“wb”);
fclose(fil);
}
int tmp=250,tmp1=250,wr=0,rr=0;
cpid=fork();
如果(cpid==-1){
佩罗尔(“福克”);
出口(1);
}
如果(cpid==0){
文件*ptr=fopen(argv[2],“wb”);
而(rr
两个明显的问题
- 您不检查
和read
调用的返回值,因此您不知道实际读取或写入了多少数据(可能比请求的数据少)write
- 第一次通过循环关闭读取文件描述符,因此在第二次和后续迭代中,它将被关闭,读取将失败。您没有注意到,因为您没有检查read的返回值
道德-始终检查您呼叫的返回值。请使用类似“下次”的方式格式化您的代码,否则很难读取这行代码,看起来可疑
读取(fildes[0],childbuff,tmp1);关闭(菲尔德斯[0])代码>为什么在从管道中读取一个缓冲区后立即关闭管道?这样做比管道、分叉和混合fread/fwrite与read/write所需要的复杂得多。这个bug可能就在那些乱七八糟的地方,但即使它工作正常,也比从文件a读然后写到文件B的简单循环要慢。如果代码工作正常与否与文件格式无关。每当文件大于您读取的一部分(250字节)时,由于close()
请不要使用,父进程将不会读取数据。它破坏#include
指令。OP:问题中的代码应该与您实际编译的代码匹配。如果重新格式化,请在将其复制到问题中之前编译重新格式化的版本。(我刚刚更正了#include
指令。)