我正在尝试使用C编程将二进制数据写入.bin文件,然后迭代以从0000写入FFFF。我想我会使用带有'wb'标签的fopen,然后能够写二进制数据,但我不确定如何使用C从0000迭代到FFFF。感谢您的帮助。
现在是我的代码:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *f = fopen("binary.bin", "wb");
unsigned long i;
//if(f == NULL) { ...error handling... }
for(i = 0x0000; i <= 0xFFFF; i++){
// Write something to the file, e.g. the 16-bit (2 byte) value of "i"
unsigned short someData = i;
fwrite(&someData, 1, 2, f);
}
fclose(f);
return 0;
//printf("Hello World\n");
getchar();
}
这将输出00 00 01 00 02 00 ...
现在是我的问题。难道这不应该读出00 00 00 01 00 02 ......开头不应该有额外的'00'吗?
另外,我一直试图看看如何复制它并扩展它因此使其成为0000 0000 0001 0001等? [更新:我刚刚复制了fwrite行并再次执行了它并解决了这个问题]
答案 0 :(得分:8)
这是将一些二进制数写入文件的简单示例。
FILE *f = fopen("yourfile", "wb");
if(f == NULL) { ...error handling... }
for(unsigned long i = 0x0000; i <= 0xFFFF; ++i)
{
// Write something to the file, e.g. the 16-bit (2 byte) value of "i"
unsigned short someData = i;
fwrite(&someData, 1, 2, f);
}
fclose(f);
请注意,此处的变量i
必须大于16位,以便它不会环绕(请参阅我对其他答案的评论)。 long
类型保证大小至少为32位。
答案 1 :(得分:5)
for (int i = 0x0000; i <= 0xffff; ++i)
答案 2 :(得分:3)
要从0
循环到0xffff
,请执行以下操作:
for (i=0; i <= 0xffff; ++i)
现在,第一个有趣的问题是,i
的类型应该是什么?在C中,unsigned int
保证保留[0, 0xffff]
范围内的值,这意味着如果i <= 0xffff
为{unsigned int i;
,UINT_MAX
将始终为真0xffff
1}}。因此i
不能是小于或等于unsigned int
的大小。 long
或unsigned long
是保证能够轻松存储0xffff + 1
的最小类型。因此,我们需要i
为unsigned long
或long
类型。在C99中,您可以通过添加stdint.h
然后使用uint32_t
类型来简化操作。
第二个有趣的问题是,你想写什么?您的文件布局是否为:
00 00 00 01 00 02 00 03 00 04 00 05 00 06 00 07
...
FF F8 FF F9 FF FA FF FB FF FC FF FD FF FE FF FF
或者您是否想使用上面您喜欢的数据类型将值写入文件,然后能够快速再次阅读它们?例如,如果int
是32位,并且您的系统是little-endian,那么编写这些值将为您提供如下文件:
00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 ...
如果你想要第一个,你必须确保按正确的顺序为每个数字写两个字节,并且操作系统的那个字节序不会影响输出。最简单的方法可能是这样的:
for (i=0; i <= 0xff; ++i) {
unsigned char values[2];
values[0] = (i & 0xff00) >> 8;
values[1] = i & 0xff;
fwrite(values, 1, 2, fp);
}
如果你想要第二种,你的生活会更容易,特别是如果你不关心这种情况:
for (i=0; i <= 0xff; ++i) {
fwrite(&i, sizeof i, 1, fp);
}
将写入您的值,以便您可以使用相同类型的变量在同一系统上读取它们。
答案 3 :(得分:2)
for (i = 0x0000; i <= 0xFFFF; ++i)
答案 4 :(得分:0)
要控制输出的 Endianess ,您必须自己编写字节(八位字节):
for (unsigned int i = 0; // Same as 0x0000
i <= 0xFFFF;
++i)
{
unsigned char c;
c = i / 256; // In Big Endian, output the Most Significant Byte (MSB) first.
fputc(/*...*/);
c = i % 256;
fputc(/*...*/);
}
当文件必须是Big Endian时,这是首选方法。无论处理器的字节顺序如何,这都将确保字节顺序。这可以调整为Little Endican的输出。
答案 5 :(得分:0)
以大端方式可移植地写入字节的替代方法:查看htons
和htonl
(以及它们的反转)。
这些转换为您的机器使用的任何格式(英特尔芯片是小端,正如几个人所指出的)到“网络”顺序(大端)。 htons
用16位字表示; {32}中的htonl
。另外一个好处是,如果您的程序在Big Endian机器上,那么这些程序将编译为no-ops。它们在<arpa/inet.h>
或<netinet/in.h>
中定义,具体取决于系统。
BSD(和Linux)还在htobe16
中提供了一组名为<endian.h>
(大端16位主机)的例程。
这些也有助于节省一次写入一个字节的开销。
如果你做想要自己提取高字节/低字节,你可能也应该使用位屏蔽来完成它。您的编译器可能足够聪明,可以将divide / modulo转换为位掩码,但如果不是,则会有令人遗憾的性能(除法慢)。
{
unsigned int x = 0xdead;
unsigned char hi = (x & 0xff00) >> 8;
unsigned char lo = (x & 0x00ff);
}
{
unsigned long int x = 0xdeadbeef;
unsigned char by0 = (x & 0xff000000) >> 24;
unsigned char by1 = (x & 0x00ff0000) >> 16;
unsigned char by2 = (x & 0x0000ff00) >> 8;
unsigned char by3 = (x & 0x000000ff);
}
(gcc
看起来很聪明,可以在分区之外进行优化,但是很好。)