首页 > 解决方案 > 在 c++ 中使用 vtd-xml 时如何摆脱 EOFException?

问题描述

我正在编写一个程序来处理 C++ 中的旧数据集。我已经设法使用James Clark 的 sx 工具将文件从 sgml 转换为 xml 。由于我过去曾在 Matlab(基于 java)中使用 vtd-xml,并且由于 vtd-xml 具有 c++ 端口,因此我决定将其用于我的项目。我正在使用vtd-xml 2.12 版,因为那是我能找到的最新版本的 c++ 端口。我设法通过将 wcsdup 的所有调用更改为 _wcsdup并使用_CRT_SECURE_NO_WARNINGS来使用 Visual Studio 2019 编译它预处理器定义。我下面的程序似乎给出了正确的输出,但在解析 xml 文件期间它也会引发异常(下面还有一个测试 xml 文件)。例外是EOFException。我没有看到我的 xml 文件有任何明显错误,并且使用下面的测试 xml 重现了该错误,这不是我从 sgml 转换的。我的直觉是,如果 c++ 端口中存在错误,那么在谷歌搜索 vtd-xml EOFException 时会更容易找到有关它的信息。因此,在我看来,我为使其编译所做的更改可能是罪魁祸首,但我不知道如何摆脱异常。任何想法都会受到欢迎。如果涉及到它,如果它是免费的,我愿意为我的程序使用不同的 xml 库。

我的代码:

#include <iostream>
#include <fstream>
#include "VTDGen.h"
#include "autoPilot.h"
#include "customTypes.h"

using namespace std;
using namespace com_ximpleware;

int main() {
    ifstream xml(".\\cd_catalog_short.xml", ios::binary | ios::ate);
    ifstream::pos_type pos = xml.tellg();
    long int length = static_cast<long int>(pos);
    char* pChars = new char[length];
    xml.seekg(0, ios::beg);
    xml.read(pChars, pos);
    xml.close();

    UCSChar node_path[] = L"/CATALOG/CD/TITLE";
    UCSChar* title;
    VTDGen vg;
    vg.setDoc(pChars, length);
    vg.parse(false);
    AutoPilot ap;
    ap.selectXPath(node_path);
    VTDNav* vn = vg.getNav();
    ap.bind(vn);
    while (ap.evalXPath() != -1) {
        int ind = vn->getText();
        if (ind != -1) {
            title = vn->toNormalizedString(ind);
            wcout << title << endl;
            delete[] title;
        }
    }
    return 0;
}

一个测试xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<CATALOG>
  <CD>
    <TITLE>For the good times</TITLE>
    <ARTIST>Kenny Rogers</ARTIST>
    <COUNTRY>UK</COUNTRY>
    <COMPANY>Mucik Master</COMPANY>
    <PRICE>8.70</PRICE>
    <YEAR>1995</YEAR>
  </CD>
  <CD>
    <TITLE>Big Willie style</TITLE>
    <ARTIST>Will Smith</ARTIST>
    <COUNTRY>USA</COUNTRY>
    <COMPANY>Columbia</COMPANY>
    <PRICE>9.90</PRICE>
    <YEAR>1997</YEAR>
  </CD>
  <CD>
    <TITLE>Tupelo Honey</TITLE>
    <ARTIST>Van Morrison</ARTIST>
    <COUNTRY>UK</COUNTRY>
    <COMPANY>Polydor</COMPANY>
    <PRICE>8.20</PRICE>
    <YEAR>1971</YEAR>
  </CD>
</CATALOG>

我的程序输出:

在 em.exe 中的 0x00007FF96A36A839 处引发异常:Microsoft C++ 异常:com_ximpleware::EOFException 在内存位置 0x0000005498B6F350。

为了美好时光

大威利风格

图珀洛蜂蜜

C:\Users\Joe\source\repos\em\x64\Release\em.exe(进程 16308)以代码 0 退出。

要在调试停止时自动关闭控制台,请启用工具->选项->调试->调试停止时自动关闭控制台。

按任意键关闭此窗口。. .

标签: c++visual-studiovtd-xml

解决方案


vtd-xml 似乎使用 EOFException 更像是一个信号,而不是真正的错误状态。我通过运行程序的 java 版本消除了错误来自为使其在 Visual Studio (C++) 中编译而进行的更改的可能性。这使用 vtd-xml (2.13-4-java) 的最新 java 版本,它仍然捕获 EOFException。如果我一直通过控制台而不是 Visual Studio IDE 运行 c++ 程序,我可能永远不会知道该异常。

这是java代码:

/* 
 * Copyright (C) 2002-2011 XimpleWare, info@ximpleware.com
 */
import com.ximpleware.*;
import com.ximpleware.xpath.*;
import java.io.*;

public class Tester {

  public static void main(String argv[]){


    VTDGen vg = new VTDGen();

        if (vg.parseFile("./cd_catalog_short.xml",false)){
        try {
            VTDNav vn = vg.getNav();
            AutoPilot ap = new AutoPilot(vn);
                    ap.selectXPath("/CATALOG/CD/TITLE");
                    int result = -1;
            int count = 0;
            while((result = ap.evalXPath())!=-1){
            System.out.print(""+result+"  ");     
            System.out.print("Element name ==> "+vn.toString(result));
            int t = vn.getText(); // get the index of the text (char data or CDATA)
            if (t!=-1)
              System.out.println(" Text  ==> "+vn.toNormalizedString(t));
            System.out.println("\n ============================== ");
            count++;
            }
            System.out.println("Total # of element "+count);
        }
            catch (NavException e){
             System.out.println(" Exception during navigation "+e);
            }
            catch (XPathParseException e){
             System.out.println(" Exception during parse "+e);
            }
            catch (XPathEvalException e){
             System.out.println(" Exception during xpath evaluation "+e);
            }
        }
  }
}

这是 jdb 中的程序输出:

jdb -classpath .;ximpleware-2.13-4-java 测试器

正在初始化 jdb ...

捕获 com.ximpleware.EOFException

推迟所有 com.ximpleware.EOFException。它将在加载类后设置。

运行测试器

设置未捕获的 java.lang.Throwable 设置延迟未捕获的 java.lang.Throwable

VM 已启动:设置延迟所有 com.ximpleware.EOFException

发生异常:com.ximpleware.EOFException(在:com.ximpleware.VTDGen.parse(),line=2,663 bci=1,597)"thread=main",com.ximpleware.VTDGen$UTF8Reader.getChar(),line =774 bci=24 774 抛出 e;

主要[1]续

7 元素名称 ==> TITLE Text ==> 美好时光

===============================

20 元素名称 ==> 标题文字 ==> 大威利风格

===============================

33 元素名称 ==> TITLE 文本 ==> Tupelo Honey

===============================

元素 3 的总数

应用程序退出


推荐阅读