当前位置: 首页 > 知识库问答 >
问题:

使用VTD-XML将大XML文件拆分为小块时出现异常

云隐水
2023-03-14

我正在开发一个小程序,将一个非常大的XML文件(超过2Gb)分成小块。

在研究了许多库之后,我选择了VTD-XML(对大文件使用VTDGenHuge),并开始开发一些代码测试。但我在读取文件的段字节时遇到了一个问题。

我得到抵消和长度:

            long [] l = vn.getElementFragment();

然后我得到结果信息:

            int offset = (int) (l[0] >> 64);
            int len = new Integer("" + l[1]);

最后,我尝试提取字节段以将其写入另一个文件:

            b = new byte[len];
            fis.read(b, offset, len); **//<===== this is the exception problem**

但我正在学习java。lang.IndexOutOfBoundsException

此外,当我为字节数组分配固定数量(例如新字节[400])时,程序结束OK,但输出文件已损坏。

我的代码:

    File fo = new File("\\path\\post_people.xml");
    FileOutputStream fos = new FileOutputStream(fo);

    int count = 0;

    File f = new File("\\path\\people.xml");
    FileInputStream fis = new FileInputStream(f);
    byte[] b;

    VTDGenHuge vg = new VTDGenHuge();
    if (vg.parseFile("\\path\\people.xml", false, VTDGenHuge.MEM_MAPPED)){

        VTDNavHuge vn = vg.getNav();

        AutoPilotHuge ap = new AutoPilotHuge();
        ap.bind(vn);
        ap.selectXPath("/people/person"); //here it could be posible add another condition

        while (ap.evalXPath() != -1) {
            long [] l = vn.getElementFragment();
            int offset = (int) (l[0] >> 64);
            int len = new Integer("" + l[1]);
            b = new byte[len];
            fis.read(b, offset, len); //<===== this is the line problem

            fos.write(b); // writing the fragment out into other file

            count++;

            if (count == 3) { //this is just a test
                break;
            }

        }

    }

XML文件示例:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<people>
    <person>
        <name>Nombre 0</name>
        <lastName>ApPaterno 1</lastName>
        <birthdate>2017-11-10T10:20:44.926-05:00</birthdate>
        <age>0</age>
        <address>
            <streetType>Tipo Calle 0</streetType>
            <streetName>Nombre de Calle 0</streetName>
            <number>0</number>
        </address>
    </person>
    <person>
        <name>Nombre 1</name>
        <lastName>ApPaterno 1</lastName>
        <birthdate>2017-11-10T10:20:44.926-05:00</birthdate>
        <age>1</age>
        <address>
            <streetType>Tipo Calle 1</streetType>
            <streetName>Nombre de Calle 1</streetName>
            <number>1</number>
        </address>
    </person>
</people>

拜托,你们能帮帮我吗,伙计们?

更新和解决方案:

最后,我应该修改的片段代码如下:

long [] l = vn.getElementFragment();
int offset = (int) (l[0] >> 64);
int len = new Integer("" + l[1]);
b = new byte[len];

fis.getChannel().position(0); //must return to position 0
fis.skip(offset); //must move to offset position
fis.read(b, 0, len);

共有1个答案

古畅
2023-03-14

正如您所指出的,代码中的主要问题在于inputstream的读取:

int offset = (int) (l[0] >> 64);
int len = new Integer("" + l[1]);
b = new byte[len];
fis.read(b, offset, len);

根据InputStream。read()'s JavaDoc:

读取的第一个字节存储在元素b[关闭]中,下一个字节存储在元素b[关闭1]中,依此类推。

这意味着您的实际缓冲区必须是lenght offset len,将字节0保留为offset 0,或者跳过输入流的第一个偏移字节,从位置0开始填充缓冲区,将len字节读取到缓冲区中。

如果将上述代码替换为

int offset = (int) (l[0] >> 64);
int len = new Integer("" + l[1]);
b = new byte[len];
fis.skip(offset);
fis.read(b, 0, len);

缓冲区应填充实际字符串表示形式的字节

<person>
    <name>Nombre 0</name>
    <lastName>ApPaterno 1</lastName>
    <birthdate>2017-11-10T10:20:44.926-05:00</birthdate>
    <age>0</age>
    <address>
        <streetType>Tipo Calle 0</streetType>
        <streetName>Nombre de Calle 0</streetName>
        <number>0</number>
    </address>
</person>
 类似资料:
  • 我需要使用VTD XML和XPath读取一个大xml并在多个节点中拆分结果。我在这里找到了一些解决方案,但它拆分了节点,但没有父级信息。 我为什么要找: XPath string: /CATALOG/MAIN/CD基于XPath的文档应该拆分 1) 初始文件: <代码> 2) 结果:文件1: <代码> 文件2: <代码> 文件3: <代码> 感谢您的时间和建议。 顺致敬意,

  • 我想把大的xml分成小块。我正在使用VTDGen将xml文件分割成小块,它可以很好地适应文件大小 代码可以很好地使用VTDGen,但当我使用vtdgenhug时,它就不工作了。 我在“byte[]xml=vn.getXML().getBytes();”处得到空值当您执行syso vn时。getXML()获取对象值。但使用“getBytes()”返回null。我不知道为什么。但如果u do“byte

  • 为了在巨大的xml文件中执行XPATH查询,我阅读了许多喜欢VTD-xml的文章,因此我复制了这些文章中的代码: 但当我运行它时没有结果,所以这意味着XML文件没有映射到内存中。。。我的问题是如何在VTD-xml中强制映射xml文件?

  • 问题内容: 我如何在Java或C中使用vtd-xml解析如下的xml文件? 任何帮助,将不胜感激。 谢谢 问题答案: 我想其中有些取决于您要如何解析文件。 这是一个“非生产”示例,其中使用了一些有用的技术,包括: XPath选择(此处仅使用“ / *”) 浏览所有同级节点 通过子节点向下看 使用AutoPilot将节点属性提取到地图中 希望能帮助到你 产生以下输出: 添加带有AutoPilot循环

  • 如何在java或C中使用vtd xml解析如下xml文件? 任何帮助都将不胜感激。 谢谢

  • 问题内容: 我只需要此XML的HEADLINE,仅在标记之间。还必须连续不断地打印消息。我怎样才能做到这一点。 问题答案: 我将为此使用javax.xml.xpathJava SE 5中包含的API。