fread() 中的 "size" 参数指的是什么?
What does the "size" argument in fread() refer to?
我正在尝试制作一个复制 .wav
文件的 header 的基本程序,这是我的尝试:
#include <stdio.h>
#include <stdint.h>
int main (void)
{
FILE* input = fopen("input.wav", "r");
FILE* output = fopen("output.wav", "w");
uint8_t header [44];
fread(header, sizeof(uint8_t), 44, input);
fwrite(header, sizeof(uint8_t), 44, output);
fclose(input);
fclose(output);
}
然而,在无法使其工作之后,我查找了如何做,显然
fread(header, sizeof(uint8_t), 44, input);
fwrite(header, sizeof(uint8_t), 44, output);
应该是
fread(header, 44, 1, input);
fwrite(header, 44, 1, output);
这让我很困惑,因为我认为第二个参数应该是您想要 fread
的数据单元类型的大小。谁能帮助我了解我所缺少的?非常感谢。
sizeof(uint8_t)
保证为 1
。有些人认为使用 sizeof
表达式而不是数字是一种很好的风格。
您可以写入 44 个大小为 1 的“块”,也可以写入 1 个大小为 44 的块。在任何一种情况下,您都尝试写入 44 个字节——两种方式的写入部分都是相同的。
不同之处在于 return 值,它报告了成功写入的块数。因此,如果您使用 1, 44
命令,那么它会准确告诉您写入了多少字节。如果您使用 44, 1
命令,那么您将获得 0
或 1
作为 return 值(并且无法知道它是否部分成功)。
同样的考虑也适用于 fread
。
FILE* input = fopen("input.wav", "r");
部分不正确:这指定以文本模式打开文件,这可能会对输入进行翻译,例如更改行尾。
相反,使用 "rb"
模式字符串以二进制模式打开。
第一个大小参数指定单个记录的大小。第二个大小参数定义要加载的记录数。 fread
returns 它加载的记录数。
因此,如果您有一个 20 字节的结构,并且您有一个文件,其中存储了 5 条记录,那么您可以像这样传递它。
if(fread(ptr, 20, 5, strm) != 5)
printf("Unable to load 5 records\n");
或者您可以像这样加载相同的文件:
if(fread(ptr, 1, 5*20, strm) != 5*20)
printf("Unable to load 5 records\n");
效果是一样的,但是第一个版本的可读性更好,因为通常你可能读取的记录不仅仅是“字节”。在应用程序逻辑的上下文中更容易理解。当然,您不必自己计算字节数,从而减少出错的机会。
同样适用于fwrite
。
所以在你上面的例子中我宁愿这样写:
// Your header is 44 bytes long (which is sizeof) but you want to read ONE header
if(fread(header, sizeof(header), 1, input) != 1)
... error reading 1 header ....
我正在尝试制作一个复制 .wav
文件的 header 的基本程序,这是我的尝试:
#include <stdio.h>
#include <stdint.h>
int main (void)
{
FILE* input = fopen("input.wav", "r");
FILE* output = fopen("output.wav", "w");
uint8_t header [44];
fread(header, sizeof(uint8_t), 44, input);
fwrite(header, sizeof(uint8_t), 44, output);
fclose(input);
fclose(output);
}
然而,在无法使其工作之后,我查找了如何做,显然
fread(header, sizeof(uint8_t), 44, input);
fwrite(header, sizeof(uint8_t), 44, output);
应该是
fread(header, 44, 1, input);
fwrite(header, 44, 1, output);
这让我很困惑,因为我认为第二个参数应该是您想要 fread
的数据单元类型的大小。谁能帮助我了解我所缺少的?非常感谢。
sizeof(uint8_t)
保证为 1
。有些人认为使用 sizeof
表达式而不是数字是一种很好的风格。
您可以写入 44 个大小为 1 的“块”,也可以写入 1 个大小为 44 的块。在任何一种情况下,您都尝试写入 44 个字节——两种方式的写入部分都是相同的。
不同之处在于 return 值,它报告了成功写入的块数。因此,如果您使用 1, 44
命令,那么它会准确告诉您写入了多少字节。如果您使用 44, 1
命令,那么您将获得 0
或 1
作为 return 值(并且无法知道它是否部分成功)。
同样的考虑也适用于 fread
。
FILE* input = fopen("input.wav", "r");
部分不正确:这指定以文本模式打开文件,这可能会对输入进行翻译,例如更改行尾。
相反,使用 "rb"
模式字符串以二进制模式打开。
第一个大小参数指定单个记录的大小。第二个大小参数定义要加载的记录数。 fread
returns 它加载的记录数。
因此,如果您有一个 20 字节的结构,并且您有一个文件,其中存储了 5 条记录,那么您可以像这样传递它。
if(fread(ptr, 20, 5, strm) != 5)
printf("Unable to load 5 records\n");
或者您可以像这样加载相同的文件:
if(fread(ptr, 1, 5*20, strm) != 5*20)
printf("Unable to load 5 records\n");
效果是一样的,但是第一个版本的可读性更好,因为通常你可能读取的记录不仅仅是“字节”。在应用程序逻辑的上下文中更容易理解。当然,您不必自己计算字节数,从而减少出错的机会。
同样适用于fwrite
。
所以在你上面的例子中我宁愿这样写:
// Your header is 44 bytes long (which is sizeof) but you want to read ONE header
if(fread(header, sizeof(header), 1, input) != 1)
... error reading 1 header ....