各位大侠,我编写了一个分析文本文件的小程序,用来分析某个文件夹中2000多个文本文件(每个文件大概在1000行,每行7数据,用";"隔开,每行第一个数据是索引),我要遍历所有文件,找出所有满足以下条件的文件名:
1.存在指定的索引值
2.索引对应的行的第6个数据的值是上一行的第6个数据的一半。
我的代码如下:(能分析成功,但jvm空闲内存会不断下降,直到耗光,不知道何原因,求大家帮忙分析一下,在线等)
FileRead.java
public class FileRead {
private File f;
private String basepath;//路径
public FileRead(String basepath){
this.basepath=basepath;
}
public String[] getFilenames(){
f =new File(basepath);
return f.list();
}
public String read(String filename) {
String content = "";
if (filename != null && filename.length() != 0) {
File f = new File(basepath+"/"+filename);
char buffer[] = new char[4096];
try {
FileReader in = new FileReader(f);
while (true) {
int length = in.read(buffer);
if (length != -1) {
content = content.concat(new String(buffer).substring(0,length));
}else break;
}
in.close();
return content;
}
catch (IOException e) {
System.out.println(e.getMessage());
}
}
return null;
}}
2. Analyse.java
public class Analyse {
List<String> half=new ArrayList<String>();
public void analyseHalf(String basepath,String index){
FileRead fr=new FileRead(basepath);
//获取文件列表
String [] flist=fr.getFilenames();
//开始遍历
for(int i=0;i<flist.length;i++){
String buffer = fr.read(flist[i]);//读取文件
String [] line=buffer.split("\n");//分解成行
buffer=null;
if(line.length<4){
continue;//小于4行的忽略
}
// 寻找索引
int beginning=line.length-1;
String today[]=null;
for(;beginning>2;beginning--){
today=line[beginning].split(";");//分解成7个数据
if(index.equals(today[0]))
break;
}
String yesterday[]=line[beginning-1].split(";");
if(Integer.parseInt(yesterday[5])>Integer.parseInt(today[5])*2){
half.add(flist[i]);
}
}
}
}
1.存在指定的索引值
2.索引对应的行的第6个数据的值是上一行的第6个数据的一半。
我的代码如下:(能分析成功,但jvm空闲内存会不断下降,直到耗光,不知道何原因,求大家帮忙分析一下,在线等)
FileRead.java
public class FileRead {
private File f;
private String basepath;//路径
public FileRead(String basepath){
this.basepath=basepath;
}
public String[] getFilenames(){
f =new File(basepath);
return f.list();
}
public String read(String filename) {
String content = "";
if (filename != null && filename.length() != 0) {
File f = new File(basepath+"/"+filename);
char buffer[] = new char[4096];
try {
FileReader in = new FileReader(f);
while (true) {
int length = in.read(buffer);
if (length != -1) {
content = content.concat(new String(buffer).substring(0,length));
}else break;
}
in.close();
return content;
}
catch (IOException e) {
System.out.println(e.getMessage());
}
}
return null;
}}
2. Analyse.java
public class Analyse {
List<String> half=new ArrayList<String>();
public void analyseHalf(String basepath,String index){
FileRead fr=new FileRead(basepath);
//获取文件列表
String [] flist=fr.getFilenames();
//开始遍历
for(int i=0;i<flist.length;i++){
String buffer = fr.read(flist[i]);//读取文件
String [] line=buffer.split("\n");//分解成行
buffer=null;
if(line.length<4){
continue;//小于4行的忽略
}
// 寻找索引
int beginning=line.length-1;
String today[]=null;
for(;beginning>2;beginning--){
today=line[beginning].split(";");//分解成7个数据
if(index.equals(today[0]))
break;
}
String yesterday[]=line[beginning-1].split(";");
if(Integer.parseInt(yesterday[5])>Integer.parseInt(today[5])*2){
half.add(flist[i]);
}
}
}
}
解决方案 »
- 关于executeQuery的问题请高手教我
- 编写一个应用程序,使用一个ArrayList演示Collection接口的功能。谢谢各位大侠!!我是初学者。
- hibernate初始化问题,急求!
- 用DatagramPacket发送数据最快能到什么程度?
- jdk1.5.0_09设置环境变量问题,高手帮忙。
- ==========getRuntime().exec的问题==========
- 请教如何分割时间段的问题
- 关于urlconnection.connection的问题
- 一个关于applet的题目,是scjp的,帮忙看看。谢谢
- 关于javaSE泛型通配符的问题,哪位大神帮忙看看,有问号的语句,详细解释一下,谢了
- 为什么?求解。。
- Java 小程序
另外随着传进来的index值不同,结果也会不一样,这就出现了有时候程序能正常退出,有时候会内存溢出
while (true) {
int length = in.read(buffer);
if (length != -1) {
content = content.concat(new String(buffer).substring(0,length));
不要忘记了,String的底层是数组,concat的底层也是申请一个更大的数组来存储而已。
new String(buffer) 这也是,在String的内部申请了数组,然后把buffer复制过去而已。
而且这句话事在循环体里,肯定有很多new了很多String的对象了,每一个 String 对象都得独立占用内存一块区域。Eden区放不下这些对象。或者有些无用的对象gc不能回收!还有报错的信息你也没有贴出来!
不知道你 所谓的 程序解析成功了 就是程序代码跑完了 结果你的JVM 还在吃内存。
是不是你用的线程定时在包程序。还是你在外面调用的时候 写了个 死循环还是怎么 。怎么条用这个
解析部分代码的方式 说清楚点。还有你如果用 content = content.concat(new String(buffer).substring(0,length)); 这个 用Stringbuffer 的话 会不会好点。对你运行过程中 声明对象少。应该会少占点内存。 但是 你说程序解析完了还在吃内存。这个问题 应该跟这个 没有多大关系。
另外随着传进来的index值不同,结果也会不一样,这就出现了有时候程序能正常退出,有时候会内存溢出
这是他的解释!题目描述得有误
另外StringBuffer我试过,效果一样的
报错是在读入文件的时候内存溢出,当然不是第一个文件啦,估计在读过1000多个文件时报错的,那些英文就不贴出来了,大家都熟悉的
我想问问 LZ 你的文件 是不是有特别大的。只是你不知道的呢?
我以前遇到过这样的一个问题
就是在解析文件 的时候 有个文件特别大我解析后 stringbuffer.toString() 的时候 就报错了。
我觉得不能。 我做过解析 每个文件 13M 到 19M 不等总共有 24个文件解析。。 也是要找到里面我需要的东西。 在把我需要的东西入库。
起初报错的原因是 读取15M 文件的时候 stringbuffer.toString()报错。后来用了文件映射内存的方式做的。
我对你这个问题真的很感兴趣。如果可以的话 我想试试。
就是这个问题,java的gc不能保证在对象没有引用后的立即释放。
所以即使有时你的流关闭了,可能jvm的内存还是被占用着。gc在执行的时间上,是不可控的,即使你调用,也不是立即回收。
...
while (true) {
int length = in.read(buffer);
if (length != -1) {
content = content.concat(new String(buffer).substring(0,length));
}else break;
}----------------------------------------------------------------
content 改为StringBuffer类型
StringBuffer content = new StringBuffer();
...
while (true) {
if (in.read(buffer) != -1) {
content.append(buffer);
}else break;
}
===============================================================
//开始遍历
for(int i=0;i<flist.length;i++){----------------------------------------
for(int i = 0 , len = flist.length ; i < len ; i++)
如果你的电脑装了JDK的话,直接在Dos下打命令"Jconsole",然后就可以查看是否有java虚拟机的内存泄露..
// 如果找不到index,结束分析
if(beginning<=2) {
line=null;
continue;
}
试试用这个:String line = null;
BufferedReader reader = new BufferedReader(new FileReader(file));
line = reader.readLine();也许真的是你new了太多的临时String对象,导致GC回收速度跟不上。
另外一个为什么要把一个文件read成一个大字符串再split?
个人认为split比较耗费资源,包括CPU和内存,尤其是字符串比较大的情况建议用BufferedReader一次读进来一行再分析:
BufferedReader br = new BufferedReader(new FileReader(new File(filename)));
String line = br.readLine();
while(line!=null) {
analyze(line);
line = br.readLine();
}
content = content.concat(new String(buffer).substring(0,length));这段百分之百是煞笔。你每次都将为string新辟一段内存,必须优化为stringbuffer。
如:
string a = "a"; //值为a,内存地址指到A
a = a + "b"; //值为ab,内存地址指到B
a = a + "c"; //值为abc,内存指到C
你无限期的合并,那么将有无限内存被浪费,gc回收速度决对跟不上。因为你的文件多,很多对象被创建了,虽然占用不大,但你2k或更多文件的积压就无法想象,所以建议在一个循环结束时把你创建的对象都释放或设置为null,以减少gc的判断,然后再执行回收。
那你的方法我自己写了。 没有出现你的问题。
有时间 你上QQ 我们聊下。
File filepath = new File(pathName); //pathName 对应路径
if (filepath.exists()) {
File[] files = filepath.listFiles();
for (File file : files) {
FileInputStream input = null;
input = new FileInputStream(file);
//处理逻辑
input.close(); //一定要及时关闭
//如果最后一行和下一个文件有关系的话,把最后一行的数据保存到一个 String中去即可
}以上逻辑占用的内存很小
这个程序和GC有很大的关系吗?
数据量那么点,造你们这么一说 那处理千万级的数据都不能用java了吧...楼主把需求说的详细的,我写写..看你的需求还是挺有意思的
我的机器是2G!