andybest
V2EX  ›  问与答

对于某些丧心病狂提供了上百兆 XML 文件的 API 要怎么破?

  •  
  •   andybest · Jul 21, 2014 · 5111 views
    This topic created in 4488 days ago, the information mentioned may be changed or developed.
    例如: http://www.meituan.com/api/v2/beijing/deals (只是例子,有比这个大很多的)

    每次读取服务器妥妥 OutOfMemoryError,除了分配给服务器更多的可用内存(土豪就没这个问题了)
    在服务器可用内存低于这个 XML 文件大小时,如何正常处理这个 API ?
    26 replies  •  2014-07-22 10:16:34 +08:00
    Livid
    Livid
    MOD
    PRO
    Jul 21, 2014 via iPhone
    1
    没有提供分页参数么?
    izoabr
    izoabr
    Jul 21, 2014
    2
    @julyclyde 你觉得这个问题怎么办?
    tabris17
    tabris17
    Jul 21, 2014
    4
    自己写一个XMLParser
    keithellis
    keithellis
    Jul 21, 2014❤️2
    5
    SAX parser
    feiyuanqiu
    feiyuanqiu
    Jul 21, 2014❤️1
    6
    PHP的话,可以用XMLReader这个扩展,它是按照文件流的方式每次按照节点来读取,读完一个节点再读下一个,不会把文件整个载入内存,php5.1以上都是自带了的,直接可以用。
    andybest
    andybest
    OP
    Jul 21, 2014
    7
    @keithellis SAX (Simple API for XML) parser 不是在初始化的时候一次将XML全部装入内存的吗?如何能解决这个问题呢?
    chmlai
    chmlai
    Jul 21, 2014❤️1
    8
    @andybest SAX 不需要, DOM 才是
    andybest
    andybest
    OP
    Jul 21, 2014
    9
    @chmlai 谢谢,SAX 是 streaming 的读取模式吗?
    bigredapple
    bigredapple
    Jul 21, 2014❤️1
    11
    SAX
    andybest
    andybest
    OP
    Jul 21, 2014
    12
    @keithellis Very useful !收藏了,十分感谢!
    kaneg
    kaneg
    Jul 21, 2014❤️1
    13
    如果你使用Java,基于事件的流式处理方式应该更适合你。示例代码:
    try {
    URL url = new URL("http://www.meituan.com/api/v2/beijing/deals");
    URLConnection connection = url.openConnection();
    connection.setConnectTimeout(5000);
    connection.setReadTimeout(60000);
    InputStream is = connection.getInputStream();
    try {
    XMLInputFactory factory = XMLInputFactory.newInstance();
    XMLEventReader xmlEventReader = factory.createXMLEventReader(new BufferedInputStream(is));
    while (xmlEventReader.hasNext()) {
    XMLEvent xmlEvent = xmlEventReader.nextEvent();

    if (xmlEvent.isStartElement()) {
    StartElement startElement = xmlEvent.asStartElement();
    System.out.println(startElement.getName().getLocalPart());
    }
    }
    } catch (Exception e) {
    System.err.println(e.getMessage());
    }
    } catch (IOException e) {
    System.err.println(e.getMessage());
    }
    xujialiang
    xujialiang
    Jul 21, 2014
    14
    IOS中,document方式会一次把xml全部读进内存的。
    Zhang
    Zhang
    Jul 21, 2014
    15
    加载完了,浏览器耗了4.42GB内存
    andybest
    andybest
    OP
    Jul 21, 2014
    16
    @Zhang 用什么方式加载的?
    fanghui
    fanghui
    Jul 21, 2014
    17
    笨方法:下载--保存文件--分文件--解析文件---
    Zhang
    Zhang
    Jul 21, 2014
    18
    @andybest safari呀
    ChiChou
    ChiChou
    Jul 21, 2014
    19
    @fanghui 分文件就破坏了 XML 的合法性。
    ChiChou
    ChiChou
    Jul 21, 2014
    20
    pull 比较适合这个场景。
    binjoo
    binjoo
    Jul 21, 2014
    21
    @meituan 我觉得你有必要来看看。。
    yangxiongwei
    yangxiongwei
    Jul 21, 2014❤️1
    22
    SAX ,事件驱动。当解析器发现元素开始、元素结束、文本、文档的开始或结束等时,发送事件,程序员编写响应这些事件的代码,保存数据。优点:不用事先调入整个文档,占用资源少;SAX解析器代码比DOM解析器代码小,适于Applet,下载。缺点:不是持久的;事件过后,若没保存数据,那么数据就丢了;无状态性;从事件中只能得到文本,但不知该文本属于哪个元素;使用场合:Applet;只需XML文档的少量内容,很少回头访问;机器内存少;
    julyclyde
    julyclyde
    Jul 21, 2014 via iPad
    23
    @izoabr sax啊大家都说了。这些都是历史遗留问题了

    lz做啥的?
    yangxiongwei
    yangxiongwei
    Jul 21, 2014
    24
    @julyclyde lz应该是做“后端开发”的,哈哈
    http://www.v2ex.com/t/123763
    julyclyde
    julyclyde
    Jul 21, 2014 via iPad
    25
    @Livid 没分页不稀罕。我甚至见过每次访问时当成执行生成这文件内容的团购网站呢
    arslion
    arslion
    Jul 22, 2014
    26
    只读的话用SAX呗~~
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   5258 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 63ms · UTC 02:16 · PVG 10:16 · LAX 18:16 · JFK 21:16
    ♥ Do have faith in what you're doing.