读取二进制文件,转换base16中的字节,格式化,写回ascii文件

时间:2015-02-18 21:02:14

标签: c++ std iostream

使用以下代码,我读取了一个可执行文件,并创建了一个用于存储变量的文件,一个简单的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个字节并将{s}字节保存在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
   };

1 个答案:

答案 0 :(得分:1)

char与unsigned int的数据类型不同。我认为你的演员表符号扩展你的char的高位(即1)并填充unsigned int的剩余24位。这是kludgey,但尝试掩盖高位。我在之前/之前尝试过这个:

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;

得到了这个输出:

enter image description here

另一个选项是将数据类型正确地更改为unsigned char。您的模板调用当前将其作为char,而不是unsigned char。这也不会掩盖。