【问题标题】:VTD-XML : XMLModifier.output() throws an IndexOutOfBoundsExceptionVTD-XML:XMLModifier.output() 抛出 IndexOutOfBoundsException
【发布时间】:2016-03-22 07:07:02
【问题描述】:

我一直在尝试使用 VTD-XML 修改 xml 文件。xml 已作为字符串从 java (JAX-WS) Web 服务接收。来自服务器的 http 响应标头具有 content type : text/xml 和 charset = utf-8。

代码如下:

private static byte[] getDataFromFile(String filePath) throws IOException {
    File file = new File(filePath);
    FileInputStream fileInputStream = new FileInputStream(file);
    byte[] byteArray = new byte[(int) file.length()];
    fileInputStream.read(byteArray);
    String fileData = new String(byteArray);
    byteArray = fileData.getBytes("UTF-16");
    return byteArray;
}

private static void cutOffXmlByXpath(String xpathQuery, String inputFilePath, String outputFilePath) throws Exception {
    byte[] byteArray = getDataFromFile(inputFilePath);

    VTDGen vg = new VTDGen();
    vg.setDoc(byteArray);
    vg.parse(false);
    VTDNav vn = vg.getNav();

    AutoPilot ap = new AutoPilot(vn);
    ap.selectXPath(xpathQuery);

    XMLModifier xm = new XMLModifier(vn);

    while((ap.evalXPath())!=-1) {
        xm.remove(vn.getElementFragment());
    }

    xm.output(outputFilePath);
}


public static void main(String[] args) {
    try {
        cutOffXmlByXpath("//Part[@identifier != 'ID Page. Interview and Profile Form' and @identifier != 'Reports']", FILE_PATH, OUTPUT_FILE_PATH);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

xml上面的声明是这样的:

<?xml version="1.0" encoding="utf-16"?>

这就是为什么我在 getDataFromFile() 方法中从 UTF-16 文件中读取字节的原因。否则,代码会引发异常,指出它无法切换到编码 UTF-16。

现在上面的代码抛出以下异常:

java.lang.IndexOutOfBoundsException
at java.io.FileOutputStream.writeBytes(Native Method)
at java.io.FileOutputStream.write(FileOutputStream.java:345)
at com.ximpleware.XMLModifier.output(XMLModifier.java:2068)
at com.ximpleware.XMLModifier.output(XMLModifier.java:2193)
at Main.cutOffXmlByXpath(Main.java:111)
at Main.main(Main.java:161)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)

如果我将文件的编码更改为 UTF-8 并相应地修改 getDataFromFile() 方法(即我们从文件 中读取字节没有指定任何编码或UTF-8作为编码)一切正常。

任何帮助将不胜感激。

【问题讨论】:

  • 你能发布一个带有那个编码头的XML文件的简化版本吗?
  • 感谢您的及时回复。我已经上传了一个文件here,使用它我已经能够重现异常。该文件是 utf-16 编码的,我已经相应地修改了 getDataFromFile() 方法(即只读取原始字节而不指定任何编码)以传递给 vtd-xml。
  • 您能通过电子邮件将这个 XML 文件或整个测试用例发送给我吗?jzhang@ximpleware.com?
  • @vtd-xml-author 我已将文件发送给您。请在您查看问题后告诉我。
  • 我会尽快回复你...

标签: java xml xml-parsing vtd-xml xml-encoding


【解决方案1】:

我将所有内容都加载到了 Eclipse 中。我得到的第一个字节是-17,它是二进制的0xef,这是一个无效的BOM起始字节。仅供参考,BOM 应该是 0xff 0xfe 或 0xfe 0xff ......所以它在解析例程中失败了......

private static byte[] getDataFromFile(String filePath) throws IOException {
        File file = new File(filePath);
        FileInputStream fileInputStream = new FileInputStream(file);
        byte[] byteArray = new byte[(int) file.length()];
        //byteArray[0]=(byte)0xff;
        //byteArray[1]=(byte)0xfe;
        //byteArray[2]=0x00;

        fileInputStream.read(byteArray);

        System.out.println(" first byte "+byteArray[0]);
        System.out.println(" second byte "+byteArray[1]);
        System.out.println(" third byte "+byteArray[2]);
        System.out.println(" length "+file.length());
        return byteArray;
    }

异常日志如下所示:

 first byte -17
 second byte -69
 third byte -65
 length 192
com.ximpleware.ParseException: XML decl error: Can't switch encoding to UTF-16
Line Number: 1 Offset: 39
    at com.ximpleware.VTDGen.matchUTFEncoding(VTDGen.java:2241)
    at com.ximpleware.VTDGen.process_dec_attr(VTDGen.java:3385)
    at com.ximpleware.VTDGen.parse(VTDGen.java:2632)
    at DOMTest.removeNode.cutOffXmlByXpath(removeNode.java:28)
    at DOMTest.removeNode.main(removeNode.java:46)

【讨论】:

  • 是的,您遇到了完全相同的错误。我正在使用 2.11。而且我也在使用相同的文件。谢谢。
  • 对不起,我的错误。请像这样修改 getDataFromFile() 方法以重现异常。 private static byte[] getDataFromFile(String filePath) throws IOException { File file = new File(filePath); FileInputStream fileInputStream = new FileInputStream(file); byte[] byteArray = new byte[(int) file.length()]; fileInputStream.read(byteArray); return byteArray; }
  • 如果我打印字节数组的第 0 个索引,我将第一个字节设为 -2。有什么线索吗?
  • 您的文件有多大? 192 字节长?我打印了前三个字节和文件的长度......你能验证你发送给我的文件还是重新发送文件?
  • 我已将文件再次发送给您。该文件的长度应为 380 字节。我将前三个字节设为 -2、-1 和 0。让我知道你发现了什么。谢谢。
猜你喜欢
  • 2023-03-28
  • 1970-01-01
  • 2013-05-20
  • 1970-01-01
  • 2020-05-11
  • 2021-12-20
  • 2018-07-31
  • 2016-06-05
  • 1970-01-01
相关资源
最近更新 更多