先说说遇到的问题:
要解析的xml文件是UTF8编码的,无法人工修改xml,因为xml是自动生成-自动解析的。某天遇到问题字符:<v>CD¡»¯ɽʮ¼ӗѭ1</v>,用UE打开是这样的,解析时报异常:
UTFDataFormatException,Message:invalid byte 1 () of a 1-byte sequence。单步跟踪分析,发现是在xerces第三方库中跑出的异常,原因应该是文件中含有非utf8的字符。
造成这个问题的原因:xml生成时,存在中文,且不是UTF8编码,但直接写进了UTF8 的xml文件中,因此当用UE打开时,就出现了乱码。
解决过程:
思路:找到抛出异常的位置,然后处理掉。
**想跟踪代码,发现使用的libxerces.so无法跟踪进入代码。咨询高人,安装时没有生成带debug信息的库。重新生成libxerces.so
执行脚本 ./runConfigure 时,加入参数-d 即: ./runConfigure -plinux -cgcc -xg++ -d -C--prefix=/opt/ApacheXML
**但跟踪很不顺利,放弃了。于是尝试把xerces源码加载到helloworld工程里,在eclipse里面读源码并查找。建立helloworld工程,在src右键粘贴源代码。xerces的源码编译起来太费劲了,干脆不管它,直接“Ctrl+H”,在所有工程里面搜索异常信息“UTFDataFormatException”,发现只有xerces/util目录下的XMLUTF8Transcoder.cpp中有这个异常,于是苦心钻研。
***transcodeFrom函数是把UTF 8转成Unicode,返回的是toFill,因为outPtr = toFill;所以需要修改的就是outPtr。
首先如果是ASCII(一字节,且小于等于127),则直接转换成2字节Unicode(*outPtr++ = XMLCh(*srcPtr++);)
如果是多字节,需要根据UTF8编码的规则判断是否是UTF8,然后进行转换。UTF8编码是边长的,XMLUTF8Transcoder.cpp中把UTF-8转换成Unicode的方法写的很详细,但真的是复杂啊,看的晕晕乎乎的。每个字节都要check是不是符合UTF 8编码规则,不符合就会抛异常。
***经高人指教,想到一个好办法,也就是不管哪个地方抛出异常,我们都把它catch住。本来是想还原字符内容转成utf8,但难度太大,就决定用“?”代替非法字符。
在ASCII码处理代码的下方try,在while结束之前catch,如下:
}catch(...)
{
unsigned char temp='?';
*outPtr++ = XMLCh(temp);
srcPtr++;
}
这样再生成libxerces.so就不会抛出异常了,非utf8字符被?取代。
可以程序先读一遍然后写成utf 8格式的文件保存,但没试过