我需要从大约100个长达200,000行的XML文件中读取前15行。有没有办法使用像BufferedReader之类的东西来有效地做到这一点? this question中列出的步骤使用DocumentBuilder.parse(String)
;这会尝试立即解析整个文件。
编辑:前15个元素包含有关文件的元数据(页面名称,最后编辑日期等),我想将其解析为表格。
答案 0 :(得分:7)
这可能是你想要做的 - 就像我在评论中写的那样,使用SAX解析器,当你的停止条件满足时,使用这个
How to stop parsing xml document with SAX at any time?
编辑:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<first>
<inner>data</inner>
</first>
<second>second</second>
<third>third</third>
<next>next</next>
</root>
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class ReadXmlUpToSomeElementSaxParser extends DefaultHandler {
private final String lastElementToRead;
public ReadXmlUpToSomeElementSaxParser(String lastElementToRead) {
this.lastElementToRead = lastElementToRead;
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
// just for showing what is parsed
System.out.println("startElement: " + qName);
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (lastElementToRead.equals(qName)) {
throw new MySaxTerminatorException();
}
}
public static void main(String[] args) throws Exception {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
try {
saxParser.parse("src/test.xml", new ReadXmlUpToSomeElementSaxParser("second"));
} catch (MySaxTerminatorException exp) {
// nothing to do, expected
}
}
public class MySaxTerminatorException extends SAXException {
}
}
startElement: root
startElement: first
startElement: inner
startElement: second
为什么这样更好?仅仅因为某些应用程序可以发送给您
<?xml version="1.0" encoding="UTF-8"?>
<root>
<first><inner>data</inner></first>
<second>second</second>
<third>third</third>
<next>next</next>
</root>
和面向行的方法将失败......
我提供了不计算元素的解析器,以显示可以根据实现所需的业务逻辑来定义条件...
要读取元素中的数据,您可以使用character()
方法,但请注意
中阅读更多内容SAX解析器可以在一个块中返回所有连续的字符数据,或者它们可以将它分成几个块
答案 1 :(得分:4)
这是一个简单的解决方案,它将逐行读取您的文件,直到它在行变量中存储15行数据(如果文件较小,则少于15行)。
File f = new File("your path");
BufferedReader br = null;
String lines = "";
try
{
br = new BufferedReader(new FileReader(f));
String line = null;
int lineCount = 0;
while((line = br.readLine()) != null)
{
lineCount++;
lines += line + "\n";
if(lineCount == 15) break;
}
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
try{br.close();}catch(Exception e){}
}
答案 2 :(得分:4)
我建议查看流式XML解析器;流API的用例扩展到读取几百GB的文件,这些文件显然不适合内存。
在Java中,StAX API是本地SAX API的(相当大的)演变。在这里查看关于解析&#34;动态&#34;:
的教程答案 3 :(得分:2)
最好像下面一样手动阅读。在你的情况下,DOM解析器将是昂贵的。如果您真的想要解析xml并提取/插入节点,则可以使用SAX解析器。
try (BufferedReader br = new BufferedReader(new FileReader("C:\\testing.txt")))
{
String sCurrentLine;
while ((sCurrentLine = br.readLine()) != null) {
System.out.println(sCurrentLine);
}
} catch (IOException e) {
e.printStackTrace();
}
答案 4 :(得分:2)
假设您想阅读以下内容:
<?xml ...?>
<root>
<element>data</element>
...
<otherElement>more data</otherElement>
<ignoredElement> ... </ignoredElement>
... more ignored Elements
</root>
并且您只希望根目录中的前13个子元素(恰好位于非常大的文件的前15行内)。
您可以使用SAX解析器读取文件,并在读取这些元素后立即将其中止。
您可以使用标准J2SE设置SAX解析器:
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader reader = sp.getXMLReader();
然后,您需要创建一个将成为数据处理程序的ContentHandler
类。我会称之为DataSaxHandler
。如果你扩展DefaultHandler
,你只需要实现你感兴趣的方法。这是一个你可以用它作为起点的例子。它将检测每个元素的开始和结束并将其打印出来。它将计算15个结束标记(它不会生成格式良好的输出)并且它将忽略属性。用它作为起点(我没有测试过):
public class DataSaxHandler extends DefaultHandler {
private int countTags = 0;
private boolean inElement = false;
@Override
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
System.out.println("<" + qName + ">");
inElement = true;
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
countTags++;
System.out.println("</" + qName + ">");
inElement = false;
if(countTags > 15) {
// throw some exception to stop parsing
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if(inElement) {
System.out.println(new String(ch, start, length));
}
}
}
您将其注册到SAX阅读器并使用它来解析文件。
reader.setContentHandler(new DataSaxHandler());
reader.parse(new InputSource(new FileInputStream(new File(PATH, "data.xml"))));