希望有人能帮忙。我的问题如下:
我正在创建包含二进制数据的文件。每个文件开头都有一个二进制标头,其中包含有关文件内容的信息。文件标头是固定大小的,为52字节。标头在标头内具有特定的信息,这些信息位于标头内的特定字节偏移量处,但某些信息仅覆盖部分字节,例如3位。
例如:
Byte 1-4 = 文件长度 Byte 5-8 = 标头长度 Byte 8-9 = 版本信息 Byte 10-13 = 文件创建时间戳
位1-4 = 月份(1-12) 位5-9 = 日(1-31) 位10-14 = 小时(0-23) 位15-20 = 分钟(0-59) 位21 = UTC偏移方向 位22-26 = UTC偏移小时 位27-32 = UTC偏移分钟
一些值是静态定义的,一些则在运行时确定。我尝试创建标头的“映射”,定义属性必须使用的位数以及所表示的值。这些存储在int对的向量中,int_pair.first是值,int_pair.second是位数。然后,我将提供的值(全部为整数)转换为二进制格式,并将二进制符号插入stringstream中。然后,我从二进制值的字符串表示中创建一个bitset,并将其写入文件。我的问题是,字节未按正确顺序显示在输出文件中。
我将省略获取值的方法,仅在我的示例中提供整数,并为简洁起见截断标头中的某些信息(因此在此示例中,标头为14个字节,而不是52个字节),但这大致是我正在做的:
实际上,我看到的是这样的:
我正在创建包含二进制数据的文件。每个文件开头都有一个二进制标头,其中包含有关文件内容的信息。文件标头是固定大小的,为52字节。标头在标头内具有特定的信息,这些信息位于标头内的特定字节偏移量处,但某些信息仅覆盖部分字节,例如3位。
例如:
Byte 1-4 = 文件长度 Byte 5-8 = 标头长度 Byte 8-9 = 版本信息 Byte 10-13 = 文件创建时间戳
位1-4 = 月份(1-12) 位5-9 = 日(1-31) 位10-14 = 小时(0-23) 位15-20 = 分钟(0-59) 位21 = UTC偏移方向 位22-26 = UTC偏移小时 位27-32 = UTC偏移分钟
一些值是静态定义的,一些则在运行时确定。我尝试创建标头的“映射”,定义属性必须使用的位数以及所表示的值。这些存储在int对的向量中,int_pair.first是值,int_pair.second是位数。然后,我将提供的值(全部为整数)转换为二进制格式,并将二进制符号插入stringstream中。然后,我从二进制值的字符串表示中创建一个bitset,并将其写入文件。我的问题是,字节未按正确顺序显示在输出文件中。
我将省略获取值的方法,仅在我的示例中提供整数,并为简洁起见截断标头中的某些信息(因此在此示例中,标头为14个字节,而不是52个字节),但这大致是我正在做的:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <bitset>
#include <vector>
#include <algorithm>
int main ()
{
vector<pair<int,int>> header_vec;
header_vec.push_back(make_pair(9882719,32)); // file length
header_vec.push_back(make_pair(52,32)); // header length
header_vec.push_back(make_pair(6,3)); // high release identifier
header_vec.push_back(make_pair(4,5)); // high version identifier
header_vec.push_back(make_pair(6,3)); // low release identifier
header_vec.push_back(make_pair(4,5)); // low version identifier
// file open timestamp
header_vec.push_back(make_pair(9,4)); // month
header_vec.push_back(make_pair(6,5)); // day
header_vec.push_back(make_pair(19,5)); // hour
header_vec.push_back(make_pair(47,6)); // min
header_vec.push_back(make_pair(0,1)); // utc direction
header_vec.push_back(make_pair(0,5)); // utc offset hours
header_vec.push_back(make_pair(0,6)); // utc offset minutes
ostringstream oss;
// convert each integer to binary representation
for ( auto i : header_vec )
{
for (unsigned int j(i.second-1); j != -1; --j)
{
oss << ((i.first &(1 << j)) ? 1 : 0);
}
}
// copy oss
string str = oss.str();
// create bitset
bitset<112> header_bits(string(str.c_str()));
// write bitset to file
ofstream output("header.out", ios::out | ios::binary );
output.write( reinterpret_cast<char *>(&header_bits), 14);
output.close();
return 0;
}
现在,大多数情况下这种方法似乎是可行的,除了比特位需要反转。如果我在fm中查看输出文件,我希望看到以下内容:
File: header.out (0x0e bytes)
Byte: 0x0
00 00 96 cc 5f 00 00 00 34 c4 c4 93 4e f0 00 ..._...4...N...O
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
实际上,我看到的是这样的:
File: header.out (0x0e bytes)
Byte: 0x0
00 00 f0 4e 93 c4 c4 34 00 00 00 5f cc 96 00 @O...N...4..._..
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
在创建位集之前,我尝试翻转字符串,但这也不能产生期望的输出。
我想我对位集的理解还不够,无法意识到为什么会发生这种情况。非常感谢任何和所有的建议!如果有其他实现方法,请分享!
提前致谢... -J
ofstream.write
调用即可。唯一有些棘手的是日期/时间戳,但这可以通过一些移位运算来完成。而且,reinterpret_cast
不是有些不安全的代码吗? - nicholas