我必须解决一个接近解析像3 GB或更高版本的巨大文件的问题。好吧,该文件的结构如下:伪xml文件如:
<docFileNo_1>
<otherItems></otherItems>
<html>
<div=XXXpostag>
</html>
</docFileNo>
... others doc...
<docFileNo_N>
<otherItems></otherItems>
<html>
<div=XXXpostag>
</html>
</docFileNo>
网上冲浪我读过有些人遇到管理文件的问题,但他们建议我用NIO映射文件。 所以我认为解决方案过于庞大,可能会让我抛出异常。所以我认为我的问题是解决2个doutbs:
所以......我试着用这种方式解决第一个问题:
提取25 MB的过程平均需要大约88秒.... 所以我想表演。
我可以进行提取吗?
答案 0 :(得分:1)
对于大型XML文件,最好使用SAX样式解析器,这些解析器不会尝试在内存中为整个XML文件构建文档对象模型。我不会尝试逐行读取XML文件,我会在SAX实现中调用适当的方法。 Oracle有一个tutorial
答案 1 :(得分:1)
无论你做什么,都不要做(伪代码):
String data = "";
for line in file {
data += line;
}
但使用StringBuilder:
StringBuilder data = new StringBuilder();
for line in file {
data.append(line);
}
return data.toString();
此外,考虑浏览文件并创建仅包含有趣部分的地图。 我假设你没有XML但只看起来有点像它,你给出的例子是对内容的公平表示。
Map<String, String> entries = new HashMap<String,String>(1000);
StringBuilder entryData = null;
for line in file {
if line starts with "<docFileNo" {
docFileNo = extract number from line;
} else if line starts with "<div=XXXpostag>" {
// Content of this entry starts here
entryData = new StringBuilder();
} else if line starts with "</html>" {
// content of this entry ends here
// so store content, and indicate that the entry is finished by
// setting data to null
entries.put(docFileNo, entryData.toString);
entryData = null;
} else if entryData is not null {
// we're in an entry as data is not null, so store the line
entryData.append(line);
}
}
地图仅包含条目大小的字符串,这使得它们更容易处理。我认为您需要根据真实数据进行调整,但这可以在大约半小时内完成测试。
线索是entryData。它不仅是构建1个条目的数据的StringBuilder,而且如果不为null,它还表示我们看到了一个开始条目标记(div),如果为null,我们看到结束标记(</html>)
表示下一个不需要存储行。
我假设您要保留doc号,并且XXXposttag是常量。
可以使用Scanner类来实现此逻辑的替代实现。
答案 2 :(得分:0)
如果你的问题是光盘部件,你可以通过使用带有大缓冲区的BufferedInputStream来加速这个过程 - 例如以下示例中为256KB:
InputStream in = new BufferedInputStream(new FileInputStream(filePath),256*1024)));
new BufferedReader(new InputStreamReader(in));
如果问题是CPU并且你有一台多核机器,你可以尝试将工作转移到一个单独的线程中。