读取二进制文件,以 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 屏蔽。