MFC : 由十六进制 RAW 字符串 ( Hex ASCII ) 生成文件

最近,LT 在用 VC6 开发一个小软件,其中有一个功能是需要由一个 CString 对象含有的十六进制形式的字符串( WinHex 中称之 Hex ASCII  : hexadecimal representation of raw data as ASCII text )生成磁盘文件。记录下实现过程以备忘。

任务

假设一个文件,用 Hex editor 打开内容如下图所示。
hex_file
有一个 CString 对象 S1 包含下图所示的十六进制内容( CString 类需要用到 MFC,头文件 afx.h )。我们的目标就是由字符串 S1 的内容在磁盘生成这个文件。

CString S1 = "B2E2CAD474657374"

实现

在 stackoverflows 和 google 网站搜索后,发现有如下秘诀:1、转换 S1 的内容,每两个字符转化为 ASCII 码。2、用 ofstream 创建对象以二进制方式写入文件。LT 实现的 VC6 代码如下:

#include "stdafx.h"
#include <afx.h>
#include <iostream>
#include <fstream>
using namespace std;

unsigned char val(char c)
{
    if ('0' <= c && c <= '9') { return c      - '0'; }
    if ('a' <= c && c <= 'f') { return c + 10 - 'a'; }
    if ('A' <= c && c <= 'F') { return c + 10 - 'A'; }
	throw "error";  // string must be hex-ascii
}

int main(int argc, char* argv[])
{
    CString S1="B2E2CAD474657374?";
    ofstream f;
    f.open("text.txt",ios::out | ios::binary);
    for (int i = 0; i < S1.GetLength(); i+=2)
    {
		try
		{
			if ((S1.GetLength() % 2) != 0) // string must be even
			{ 
				throw "error"; 
			} 
			unsigned  char n = val(S1[i]) * 16 + val(S1[i + 1]);
			f.put(n);
			cout<<n;
		}

		catch (...) 
		{
			cout<<"excep catched! must check the string !\n "<<endl;
			exit(-1);
		}

    }

    f.close();
    cout<<endl;
    return 0;
}

 

效果

编译(VC项目属性设置:去除头文件预编译;用 MFC 动态 dll 链接库)执行后,打开程序生成的 text.txt 文件,效果如下,与我们预期一致:

hex_file_2

实际测试,7M byte 的 CString 对象也可以正确处理。本文源码下载:cstring HexAscii

后记

刚开始在VC6中使用ofstream用的下面的头文件,但是会发现在VS2010中编译通不过。

#include <fstream.h>

后来查资料得知 <fstream.h> 不是标准的C++写法,改为下面的写法,就可以。

#include <fstream>
using namespace std;

还有,考虑到 CString 来源中含有非十六进制字符以及字符个数是否为偶数,需要增加异常处理机制。在希望捕捉异常的地方用 try 括起来,throw 抛出异常,catch(…) 捕获所有异常。

try
{
  //需要捕捉异常的程序运行片段
}
catch(...)
{
  //异常处理
}

 思考

如何将这个过程逆序处理,即由读取文件来获取十六进制RAW字符串?

扩展阅读

关键字:MFC, HEX, CString, fstream, ofstream, C++, Hex ASCII, HexASCII, 十六进制, 文件, 异常处理, try, catch

4 thoughts on “MFC : 由十六进制 RAW 字符串 ( Hex ASCII ) 生成文件

  1. 提供一个 Python 版的(简易)。

    with open(‘test.txt’, ‘w’) as f:
    f.write(‘B2E2CAD474657374’.decode(‘hex’))

    这个 decode 过程实质上用了标准库 binascii —— Python 就是「内置电池」啊 🙂

  2. Pingback: 二进制文件的XML存储方式 | LT

Leave a Reply

Your email address will not be published. Required fields are marked *