以下不算是教程,完全可以作为一个开胃菜,思考下。
相信百度“java内存溢出”或者“java内存泄漏”的文章,都会有很多详细描述,代码举例。这里推荐我看过的文章。
http://blog.csdn.net/anxpp/article/details/51325838
再说下我之前的面试经历。
被问到印象深刻的编程经历,当时自己写个关于【在指定文件夹下的文件中查找指定字符串】的程序,然后这个程序其实写出来大家都会觉得简单,确实如此。但是如果这些文件比较多,每个文件都比较大呢,我的代码确实出现了问题,具体如下:
在文件名带有【anr】和【crash】的文件夹中的所有文件中找到【Process】和【Flags】字符串中间的内容,并反馈属于哪个文件。我刚开始写的代码如下,使用的是jdk1.6。
package cn.com.tianll.test;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
/**
遍历某文件夹下的文件txt,找到指定txt文件并返回该txt文件中指定的字符串
@author tianll
2016-7-13 22:36:54
*/
public class FindInfo {
private static ArrayList<String> filelist = new ArrayList<String>();//用于存储跟文件夹名称
private static String str = "";//用于存储某个文件中需要的信息
private static String strsum = "";//用于存储遍历所有文件夹后的需要的信息
public static void main(String args[]) throws IOException{
String filePath = "H:\startdima\2016_06_27_13_29_58_ap_log\sdcard";
getFiles(filePath);
}
private static void getFiles(String filePath) throws IOException {
File root = new File(filePath);
File[] files = root.listFiles();
for(File file : files) {
String path = "";
if(file.isDirectory()){
path = file.getAbsolutePath();
getFiles(path);
filelist.add(path);
// System.out.println("111显示"+filePath+"下所有子目录及其文件"+path);
}else{
// System.out.println("222显示"+filePath+"下所有子目录"+file.getAbsolutePath());
//如果文件是txt文件,则查看文件名是否含有指定字符名称anr和crash
path = file.getAbsolutePath();
// if(path.contains(".xml")){
if(path.contains("anr")||path.contains("crash")){
System.out.println("----------------"+path);
BufferedReader bf = new BufferedReader(new InputStreamReader(new FileInputStream(path)));
String line = "" ;//表示读取的每行xml信息
str = "";
while((line =bf.readLine()) != null){
System.out.println("*"+line);
str = str+"\r\n"+line ;
}
if(str.contains("Process")&&str.contains("Flags")){
int index1 = str.indexOf("Process")+7;
int index2 = str.indexOf("Flags")+5;
System.out.println(index1);
System.out.println(index2);
if(index1<index2){
str = str.substring(index1 , index2);
}
}
// if(str.contains("000597922950008")){
// System.out.println(path+"+++");
// }
}
// }
strsum = strsum +str ;
System.out.println("strsum="+strsum);
}
}
}
}
之后面试说了这件事,问我原因,当时没有在意这个问题,直到我后来看了写内存泄露内存溢出的文章恍然大悟。测试文件比较小的时候没什么问题,文件多而且大的时候会出现OutOfMemory问题,这时候就需要优化代码了。优化如下,使用jdk1.7。具体更换jdk原因可以看内存泄漏中substring()方法在1.6和1.7中的区别,在1.7中移除永久代中的字符常量池。
package cn.com.tianll.test;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
/**
遍历某文件夹下的文件txt,找到指定txt文件并返回该txt文件中指定的字符串
@author tianll 复制FindInfo
2018-1-5 15:16:42,就行修改,已经修改完成。
*/
public class FindInfo1 {
private ArrayList<String> filelist = new ArrayList<String>();// 用于存储跟文件夹名称
private StringBuffer str = new StringBuffer();// 用于存储某个文件中需要的信息
private String strString = "";
private StringBuffer strA = new StringBuffer();// 用于存储某个文件中需要的信息 当前行
private StringBuffer strB = new StringBuffer();// 用于存储某个文件中需要的信息 上一行
public static void main(String args[]) throws IOException {
String filePath = "H:\startdima\2016_06_27_13_29_58_ap_log\sdcard";
new FindInfo1().getFiles(filePath);
}
private void getFiles(String filePath) throws IOException {
File root = new File(filePath);
File[] files = root.listFiles();
for (File file : files) {
String path = "";
if (file.isDirectory()) {
path = file.getAbsolutePath();
getFiles(path);
filelist.add(path);
} else {
path = file.getAbsolutePath();
if (path.contains("anr") || path.contains("crash")) {
System.out.println(path);
@SuppressWarnings("resource")
BufferedReader bf = new BufferedReader(
new InputStreamReader(new FileInputStream(path)));
String line = "";
while ((line = bf.readLine()) != null) {
strA.append(line);
str.append(strA);
str.append(strB);
strString = str.toString();
if (str.toString().contains("Process")
&& str.toString().contains("Flags")) {
int index1 = strString.indexOf("Process") + 7;
int index2 = strString.indexOf("Flags") + 5;
if (index1 < index2) {
strString = str.substring(index1, index2);
System.out.println("输出:"+strString);
}
}
strB = new StringBuffer("") ;
strB.append(line);
strA = new StringBuffer("") ;
str = new StringBuffer("") ;
}
}
}
}
}
}