我有DATE NAME MESSAGE
形式的大量制表符分隔文本数据。我的意思是,1.76GB的集合分为1075个实际文件。我必须从所有文件中获取NAME
数据。直到现在我有了这个:
File f = new File(directory);
File files[] = f.listFiles();
// HashSet<String> all = new HashSet<String>();
ArrayList<String> userCount = new ArrayList<String>();
for (File file : files) {
if (file.getName().endsWith(".txt")) {
System.out.println(file.getName());
BufferedReader in;
try {
in = new BufferedReader(new FileReader(file));
String str;
while ((str = in.readLine()) != null) {
// if (all.add(str)) {
userCount.add(str.split("\t")[1]);
// }
// if (all.size() > 500)
// all.clear();
}
in.close();
} catch (IOException e) {
System.err.println("Something went wrong: "
+ e.getMessage());
}
}
}
即使使用-Xmx1700,我的程序总是会出现内存异常。我无法超越这一点。无论如何我可以优化代码,以便它可以处理ArrayList<String>
的{{1}}?
答案 0 :(得分:3)
由于您似乎允许使用替代解决方案而不是Java,因此这是一个应该处理它的awk。
cat *.txt | awk -F'\t' '{sum[$2] += 1} END {for (name in sum) print name "," sum[name]}'
说明:
-F'\t' - separate on tabs
sum[$2] += 1 - increment the value for the second element (name)
关联数组使这非常简洁。在我创建的测试文件上运行它,如下所示:
import random
def main():
names = ['Nick', 'Frances', 'Carl']
for i in range(10000):
date = '2012-03-24'
name = random.choice(names)
message = 'asdf'
print '%s\t%s\t%s' %(date, name, message)
if __name__ == '__main__':
main()
我得到了结果:
Carl,3388
Frances,3277
Nick,3335
答案 1 :(得分:1)
您可以采取一些措施来改善代码的内存占用和一般性能:
关闭FileReader对象,然后再转到下一个。 FileReader是一个InputStreamReader,需要调用close()
才能释放资源。您当前的代码实际上为您正在查看的每个文件保持流打开。
for( File file: files ) {
BufferedReader in = null;
try{
in = new BufferedReader( new FileReader( file ) );
// TODO do whatever you want here.
}
finally{
if( in != null ) {
in.close();
}
}
}
如果可能,请删除在NAME
ArrayList中存储所有userCount
值。与A. R. S.建议的一样,您可以先将此信息写入另一个文件,然后在需要再次提取该数据时再读取该文件。如果这不是一个有吸引力的选项,您仍然可以将您的信息写入OutputStream,然后将其传送到应用程序中其他位置的InputStream。这会将您的数据保存在内存中,但无论您在何处使用NAME
值列表,都可以开始处理/显示/同时进行任何操作,因为您继续阅读这些1,000多个文件以搜索更多NAME
值。
答案 2 :(得分:1)
String.split返回在内部使用与原始String相同的字符数组的字符串。未使用的字符不会被垃圾收集。
尝试使用新的String(str.split(“\ t”)[1])来强制分配新数组。