我尝试读取超过400万行和超过400 MB的日志文件,但我得到Out of Memory Error:java堆空间.这是我的代码:
File file = new File("C:\\file.log");
FileReader fileReader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(fileReader);
StringBuilder stringBuffer = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
stringBuffer.append(line);
}
Run Code Online (Sandbox Code Playgroud)
我试图将堆内存增加到1GB,但仍然得到该消息.可能的原因是什么?
See*_*ose 20
好的,你已经有了线索,阅读你得到的评论.
问题解释:
您的日志文件大小为400MB.请注意,这是以字节为单位.现在,您逐行读取它,line = bufferedReader.readLine()
从而将一些字节转换为字符串.
String
Java中的一个实例内部拥有一个char[]
.但char
Java中需要2个字节!所以你需要至少800MB的堆空间来存储所有的字符.由于您还要分配其他几个对象,并且JVM本身需要一些内存,因此很可能1 GB是不够的.
此外,StringBuffer
(顺便说一句:更好地使用StringBuilder
)内部再次使用a char[]
,在需要时自动扩展(长度).这种扩展是通过加倍长度来完成的.因此,对于400MB的文件,它char[]
的长度为512M.仍然提醒:一个字符需要2个字节.
那么解决方案是什么?简单地说:不要将整个文件读入内存!
这样做:
class LogAnalyzer {
private final File logFile;
LogAnalyzer(File logFile) {
this.logFile = logFile;
}
void analyze() throws IOException {
try(FileReader fileReader = new FileReader(logFile)) {
try(BufferedReader bufferedReader = new BufferedReader(fileReader)) {
String line;
while ((line = bufferedReader.readLine()) != null) {
analyzeLine(line);
}
}
}
}
private void analyzeLine(String line) {
// do whatever you need here
}
}
Run Code Online (Sandbox Code Playgroud)
如果需要保留一些行,则应将它们存储在LogAnalyzer的某些实例字段中,和/或使此类的行为类似于状态机.
归档时间: |
|
查看次数: |
9727 次 |
最近记录: |