读取二进制文件,以 base16 格式转换字节,格式化,写回 ascii 文件
read binary file, translate bytes in base16, format, write back in an ascii file
使用以下代码,我读取了一个可执行文件并创建了一个用于存储变量的文件,一个简单的 C char array
。
ifstream fIn( argv[1], ios::binary );
if( !fIn.is_open() )
throw (exception("Could not open file."));
ofstream fOut( argv[2] );
if( !fOut.is_open() )
throw (exception("Could not create file."));
// def of the C array
// name of the variable which will be write in the new file
fOut << "unsigned char " << varName << "[] =\n{"; // varName = "foobar";
stringstream ss;
string s;
static char c = 0;
// copy each byte in 's'
while(fIn.get(c)) s += c;
// generate the file
fOut << for_each(s.begin(), s.end(), hexify<char>(ss));
// end of def
fOut << "\n};\n";
hexify<T> struct
正文和operator<<
用来满足我的格式化需求
template<typename T> struct hexify
{
hexify(stringstream& out) : _ss(out), _n(0) {}
void operator() (T& x)
{
if( _n > 0 ) _ss << ", ";
if( (_n % 16) == 0 ) _ss << "\n\t";
_ss << "0x" << setbase(16) << setw(2) << setfill('0') << (unsigned int)x;
_n++;
}
stringstream& _ss;
int _n;
};
template<typename T>
ostream& operator<<( ostream& os, const hexify<T>& h ) { os << h._ss.str(); return os; }
-
对于这种情况,让我说我只读取文件的 前 4 个字节 并将这些字节保存在 char
数组 foobar[]
中:
4d5a 9000 0300 0000 0400 0000 ffff 0000
我期望 foobar array
定义 (在之前创建的文件中) 的结果应该是:
unsigned char foobar[] = { 0x4d, 0x5a, 0x90, 0x00 };
我自己得到的结果:
unsigned char foobar[] = { 0x4d, 0x5a, 0xffffff90, 0x00 };
为什么第三个字节用'f'包裹起来?
另一个 112 字节的例子:
unsigned char foobar[] =
{
0x4d, 0x5a, 0xffffff90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xffffffff, 0xffffffff, 0x00, 0x00,
0xffffffb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfffffff0, 0x00, 0x00, 0x00,
0x0e, 0x1f, 0xffffffba, 0x0e, 0x00, 0xffffffb4, 0x09, 0xffffffcd, 0x21, 0xffffffb8, 0x01, 0x4c, 0xffffffcd, 0x21, 0x54, 0x68,
0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20
};
char 与 unsigned int 不是同一数据类型。我认为您的演员表是对 char 的高位(即 1)进行符号扩展并填充 unsigned int 的剩余 24 位。这很麻烦,但请尝试屏蔽掉高位。我试过这个 after/before:
char y = 0x90;
cout << "0x" << hex << setw(2) << setfill('0') << (unsigned int)(y&0xFF) << endl;
cout << "0x" << hex << setw(2) << setfill('0') << (unsigned int)y << endl;
得到这个输出:
另一种选择是将您的数据类型也正确更改为无符号字符。您的模板调用当前将其作为 char,而不是 unsigned char。这也将 w/o 屏蔽。
使用以下代码,我读取了一个可执行文件并创建了一个用于存储变量的文件,一个简单的 C char array
。
ifstream fIn( argv[1], ios::binary );
if( !fIn.is_open() )
throw (exception("Could not open file."));
ofstream fOut( argv[2] );
if( !fOut.is_open() )
throw (exception("Could not create file."));
// def of the C array
// name of the variable which will be write in the new file
fOut << "unsigned char " << varName << "[] =\n{"; // varName = "foobar";
stringstream ss;
string s;
static char c = 0;
// copy each byte in 's'
while(fIn.get(c)) s += c;
// generate the file
fOut << for_each(s.begin(), s.end(), hexify<char>(ss));
// end of def
fOut << "\n};\n";
hexify<T> struct
正文和operator<<
用来满足我的格式化需求
template<typename T> struct hexify
{
hexify(stringstream& out) : _ss(out), _n(0) {}
void operator() (T& x)
{
if( _n > 0 ) _ss << ", ";
if( (_n % 16) == 0 ) _ss << "\n\t";
_ss << "0x" << setbase(16) << setw(2) << setfill('0') << (unsigned int)x;
_n++;
}
stringstream& _ss;
int _n;
};
template<typename T>
ostream& operator<<( ostream& os, const hexify<T>& h ) { os << h._ss.str(); return os; }
-
对于这种情况,让我说我只读取文件的 前 4 个字节 并将这些字节保存在 char
数组 foobar[]
中:
4d5a 9000 0300 0000 0400 0000 ffff 0000
我期望 foobar array
定义 (在之前创建的文件中) 的结果应该是:
unsigned char foobar[] = { 0x4d, 0x5a, 0x90, 0x00 };
我自己得到的结果:
unsigned char foobar[] = { 0x4d, 0x5a, 0xffffff90, 0x00 };
为什么第三个字节用'f'包裹起来?
另一个 112 字节的例子:
unsigned char foobar[] =
{
0x4d, 0x5a, 0xffffff90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xffffffff, 0xffffffff, 0x00, 0x00,
0xffffffb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfffffff0, 0x00, 0x00, 0x00,
0x0e, 0x1f, 0xffffffba, 0x0e, 0x00, 0xffffffb4, 0x09, 0xffffffcd, 0x21, 0xffffffb8, 0x01, 0x4c, 0xffffffcd, 0x21, 0x54, 0x68,
0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20
};
char 与 unsigned int 不是同一数据类型。我认为您的演员表是对 char 的高位(即 1)进行符号扩展并填充 unsigned int 的剩余 24 位。这很麻烦,但请尝试屏蔽掉高位。我试过这个 after/before:
char y = 0x90;
cout << "0x" << hex << setw(2) << setfill('0') << (unsigned int)(y&0xFF) << endl;
cout << "0x" << hex << setw(2) << setfill('0') << (unsigned int)y << endl;
得到这个输出:
另一种选择是将您的数据类型也正确更改为无符号字符。您的模板调用当前将其作为 char,而不是 unsigned char。这也将 w/o 屏蔽。