Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/344.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在java或php中解析一个非常大的xml文件并将其插入mysql数据库_Java_Php_Xml_Sax - Fatal编程技术网

如何在java或php中解析一个非常大的xml文件并将其插入mysql数据库

如何在java或php中解析一个非常大的xml文件并将其插入mysql数据库,java,php,xml,sax,Java,Php,Xml,Sax,我正试图将一个巨大的xml文件解析到我的MySQL数据库中。该文件为4.7gb。我知道,这太疯狂了 数据来自这里:(最新的相册xml压缩为700mb,解压为4.7gb) 我可以使用java或php来解析和更新数据库。我认为java是更聪明的想法 我需要找到一种在不填充4gb内存的情况下解析xml的方法,并将其加载到数据库中 最聪明的方法是什么?我听说过SAX解析器,我的想法正确吗 现在,我不关心从那些URL下载图像,我只想把数据放在我的数据库中。我还没有设计表,但我现在对xml方面更感兴趣 我使

我正试图将一个巨大的xml文件解析到我的MySQL数据库中。该文件为4.7gb。我知道,这太疯狂了

数据来自这里:(最新的相册xml压缩为700mb,解压为4.7gb)

我可以使用java或php来解析和更新数据库。我认为java是更聪明的想法

我需要找到一种在不填充4gb内存的情况下解析xml的方法,并将其加载到数据库中

最聪明的方法是什么?我听说过SAX解析器,我的想法正确吗

现在,我不关心从那些URL下载图像,我只想把数据放在我的数据库中。我还没有设计表,但我现在对xml方面更感兴趣

我使用php的fread()打开文件的前1000个比特,这样至少我可以看到它的样子,下面是文件中第一个相册的结构示例:

<releases>
<release id="1" status="Accepted">
    <images>
        <image height="600" type="primary" uri="http://s.dsimg.com/image/R-1-1193812031.jpeg" uri150="http://s.dsimg.com/image/R-150-1-1193812031.jpeg" width="600" />
        <image height="600" type="secondary" uri="http://s.dsimg.com/image/R-1-1193812053.jpeg" uri150="http://s.dsimg.com/image/R-150-1-1193812053.jpeg" width="600" />
        <image height="600" type="secondary" uri="http://s.dsimg.com/image/R-1-1193812072.jpeg" uri150="http://s.dsimg.com/image/R-150-1-1193812072.jpeg" width="600" />
        <image height="600" type="secondary" uri="http://s.dsimg.com/image/R-1-1193812091.jpeg" uri150="http://s.dsimg.com/image/R-150-1-1193812091.jpeg" width="600" />
    </images>
    <artists>
        <artist>
            <name>Persuader, The</name>
        </artist>
    </artists>
    <title>Stockholm</title>
    <labels>
        <label catno="SK032" name="Svek" />
    </labels>
    <formats>
        <format name="Vinyl" qty="2">
            <descriptions>
                <description>12"</description>
            </descriptions>
        </format>
    </formats>
    <genres>
        <genre>Electronic</genre>
    </genres>
    <styles>
        <style>Deep House</style>
    </styles>
    <country>Sweden</country>
    <released>1999-03-00</released>
    <notes>Recorded at the Globe studio in Stockholm. The titles are the names of Stockholm's districts.</notes>
    <master_id>5427</master_id>
    <tracklist>
        <track>
            <position>A</position>
            <title>Östermalm</title>
            <duration>4:45</duration>
        </track>
        <track>
            <position>B1</position>
            <title>Vasastaden</title>
            <duration>6:11</duration>
        </track>
        <track>
            <position>B2</position>
            <title>Kungsholmen</title>
            <duration>2:49</duration>
        </track>
        <track>
            <position>C1</position>
            <title>Södermalm</title>
            <duration>5:38</duration>
        </track>
        <track>
            <position>C2</position>
            <title>Norrmalm</title>
            <duration>4:52</duration>
        </track>
        <track>
            <position>D</position>
            <title>Gamla Stan</title>
            <duration>5:16</duration>
        </track>
    </tracklist>
</release>

说服者
斯德哥尔摩
12"
电子的
深屋
瑞典
1999-03-00
在斯德哥尔摩的环球影城录制。标题是斯德哥尔摩地区的名称。
5427
A.
Östermalm
4:45
地下一层
瓦萨斯塔登
6:11
地下二层
国王岛
2:49
C1
Södermalm
5:38
C2
马尔姆
4:52
D
老城区
5:16


谢谢。

如果我想用PHP解析它,我将分两步进行:

  • 每隔几个
    节点拆分一次文件,并使该小文件成为有效的XML
  • 分别解析每个结果文件

  • 如果速度不是关键,那么PHP实际上会更好,因为在PHP中解析文本/XML很容易。

    我不久前也遇到过类似的问题。下面是脚本的一部分,它导入了大约28MB的文件,而不是将整个数据读入内存。它可能会工作:)。它通过XML节点读取,在内存中只保留XM的一小部分L.脚本只需稍加修改即可满足您的需要

    $reader = new XMLReader();
    $reader->open(<path_to_large_xml_file>);    
    while ($reader->read()) {
        switch ($reader->nodeType) {
            case (XMLREADER::ELEMENT):
            if ($reader->localName == "Table") {
    
                $node = $reader->expand();
                $dom = new DomDocument();
                $n = $dom->importNode($node,true);
                $dom->appendChild($n);
                $sxe = simplexml_import_dom($n);
    
                $Data = array();
                $DataColumns = array();
    
                foreach ($columns as $key => $column)
                {
    
                    if (in_array($key,$DateColumns))
                    {
                        $DateArray = explode('/',substr(trim($sxe->$column),0,10));   
                        $ValueColumn = date('Y-m-d H:i:s',mktime(0,0,0,$DateArray[1],$DateArray[0],$DateArray[2]));
                        $Data[] = '\''.$ValueColumn.'\'';
                        $DataColumns[] = $key;
    
                        if ($SplitDateInsert == 'enabled')
                        {
                            $Data[] = '\''.$DateArray[2].'\'';
                            $Data[] = '\''.$DateArray[1].'\'';
                            $Data[] = '\''.$DateArray[0].'\'';
    
                            $DataColumns[] = $key.'_year';
                            $DataColumns[] = $key.'_month';
                            $DataColumns[] = $key.'_day';                            
                        }
    
                    } else {
                        $ValueColumn = addslashes(trim($sxe->$column));
                        $Data[] = '\''.$ValueColumn.'\'';
                        $DataColumns[] = $key;
                    }                   
    
                }               
                    $SQL = "INSERT INTO {$tableName} (".implode(',',$DataColumns).") VALUES (".implode(',',$Data).")";                  
                    $db->query($SQL);                       
    
            } // END IF table
        }
    }
    
    $reader=newXMLReader();
    $reader->open();
    而($reader->read()){
    开关($reader->nodeType){
    大小写(XMLREADER::元素):
    如果($reader->localName==“Table”){
    $node=$reader->expand();
    $dom=新的DomDocument();
    $n=$dom->importNode($node,true);
    $dom->appendChild($n);
    $sxe=simplexml\u import\u dom($n);
    $Data=array();
    $DataColumns=array();
    foreach($key=>$column的列)
    {
    if(在数组中($key,$DateColumns))
    {
    $DateArray=explode('/',substr(trim($sxe->$column),0,10));
    $ValueColumn=date('Y-m-dh:i:s',mktime(0,0,0,$DateArray[1],$DateArray[0],$DateArray[2]);
    $Data[]='\'.$ValueColumn'\'';
    $DataColumns[]=$key;
    如果($SplitDateInsert=='enabled')
    {
    $Data[]='\'.$DateArray[2].'\';
    $Data[]='\''.$DATEARRY[1].\'';
    $Data[]='\''.$DATEARRY[0].\'';
    $DataColumns[]=$key.“U年”;
    $DataColumns[]=$key.“u月”;
    $DataColumns[]=$key.“U日”;
    }
    }否则{
    $ValueColumn=addslashes(trim($sxe->$column));
    $Data[]='\'.$ValueColumn'\'';
    $DataColumns[]=$key;
    }                   
    }               
    $SQL=“插入到{$tableName}(“.introde(',',$DataColumns)。”)值(“.introde(',',$Data)。”)”;
    $db->query($SQL);
    }//结束IF表
    }
    }
    
    显然,您需要的是流式API而不是DOM,因为DOM需要将整个文档保存在内存中。Java支持SAX和。我本人从未使用过Stax,但听说它比SAX更易于使用,同时仍然很高效


    还要确保将工作拆分为多个事务:数据库无法在单个事务中支持多个insert语句。

    假设MySQL在这方面具有与Oracle类似的功能,为什么不让DB处理解析?在Oracle中,您可以注册XMLSchema,创建结构化的XMLType t可以(可能比clob更有用),然后插入文件


    从来没有在这么大的地方使用过它,但我不明白为什么它不应该工作,它只需要几行代码就可以完成。你只需要有MySQL经验的人来告诉你细节是如何工作的。

    我建议在Java上使用Stax。或者更简单一点,这会增加访问的便利性


    但是,您需要对XML做什么呢?要在DB中对其进行流式处理,有一些方法可以将blob作为流处理(尽管mySQL JDBC驱动程序因其怪癖而臭名昭著)所以,应该是可行的。

    < 4.7 GB不是疯狂的,只是温和的。如果你有64位java,扩展应该是最有效和最容易使用的选项。

    < p>你没有说过你想用XML处理什么。你可以考虑使用撒克逊的流模式XSLT(它需要的是撒克逊EE产品,它需要钱)-如果处理本质上是依次处理每个“release”元素的“突发模式流”练习,那么它应该不会太难。当然,您也可以使用低级SAX o