微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

fread() 和 fwrite() 可以用来复制 jpegs 吗?

如何解决fread() 和 fwrite() 可以用来复制 jpegs 吗?

我对编程很陌生,我正在尝试编写一个基本程序来复制 jpeg 文件

#include <stdio.h>

int main (void)
{
    FILE *a = fopen("pic1.jpg","r");
    
    FILE *b = fopen("pic2.jpg","w");
    
    fread(a,1,sizeof(a),b);
    fwrite(a,b);
    
    fclose(a);
    fclose(b);
}

程序确实创建了一个文件 pic2.jpg,但是,当我尝试查看它时,我收到错误消息:Invalid or Unsupported Image Format,所以这让我觉得我可能正在尝试使用它功能不正确。

解决方法

是的,但您没有正确使用它们。

fread(a,1,sizeof(a),b) 表示从 b sizeof(a) 次读取 1 个字节到 FILE *a 中。这可以编译,但没有多大意义。您在使用 fwrite 时犯了类似的错误。

sizeof(a) 获取 FILE * 指针的大小,通常为 8 字节,而不是文件的大小。所以你只读取和写入 8 个字节。

freadfwrite 的第一个参数是读取和写入的缓冲区,这是缺少的关键元素。


首先,始终检查您的文件操作是否有效。如果它们失败,如果文件不存在或无法打开,程序将继续愉快地运行,并且在尝试写入 NULL 时会出现奇怪的错误。

有些系统区分“二进制”和“文本”文件。您必须添加 b 标志以确保它们不会破坏内容。

我还将使用更具描述性的名称,以免混淆。

FILE *in = fopen("pic1.jpg","rb");
if( !in ) {
    perror("can't open pic1.jpg for reading");
}

FILE *out = fopen("pic2.jpg","wb");
if( !out ) {
    perror("can't open pic2.jpg for writing");
}

现在我们需要分配一个缓冲区来读取和写入。为了获得最佳性能,这应该类似于磁盘的自然块大小。 4096 或 BUFSIZ 常数是不错的选择。我们使用 char 作为字节数组的代理。如果您想花哨,可以使用 uint8_t,但由于我们只是复制字节,因此没有实际区别。

读入并在循环中写入直到所有内容都被读取。

char buf[BUFSIZ];
size_t bytes_read;

// Read a buffer sized hunk.
while( (bytes_read = fread(buf,sizeof(buf),in)) ) {
    // Write the hunk,but only as much as was read.
    fwrite(buf,bytes_read,out);
}

fclose(in);
fclose(out);

我们可以在这里使用 sizeof(buf) 只是因为 buf 是一个已知大小的数组。它将返回缓冲区的大小,而不是 char * 指针的大小。

我们必须小心地只写入我们读取的内容,而不是整个缓冲区。否则,如果我们执行 fwrite(buf,out) 并且最后一次读取仅部分填充了缓冲区,我们将打印垃圾。

fread 返回读取的“项目”数,而不是字节数。这是从 waaay 回来的,当时文件更有可能具有固定大小的记录。为了让它返回字节数,我们告诉它每个“项目”是 1 个字节,我们想要 sizeof(buf) 个“项目”。


版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。