Exception in thread "main" java.lang.OutOfMemoryError

J2EE 码拜 10年前 (2015-04-04) 936次浏览 0个评论
 

我想把一个300M的txt文档用java读取之后内容存到string中代码如下:

FileInputStream fis = new FileInputStream(files[i]);  
         String content = “”;  
         BufferedReader reader = new BufferedReader(new InputStreamReader(fis));  
           
         StringBuffer buffer = new StringBuffer(“”);  
         content = reader.readLine();  
         while (content != null) {  
             buffer.append(content);  
             content = reader.readLine();  
         }  
可是一运行就提示了这个错误

Exception in thread “main” java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Unknown Source)
at java.lang.AbstractStringBuilder.expandCapacity(Unknown Source)
at java.lang.AbstractStringBuilder.ensureCapacityInternal(Unknown Source)
at java.lang.AbstractStringBuilder.append(Unknown Source)
at java.lang.StringBuffer.append(Unknown Source)
at com.langhua.Indexer.main(Indexer.java:60)
这是因为内存不够吗?是不是不能将这么大的文件存为string类型??

Exception in thread "main" java.lang.OutOfMemoryError
300m估计你记事本都打不开 内存够大的话这个方法存在可能,但是这样效率低下
Exception in thread "main" java.lang.OutOfMemoryError
300m的文件放进内存,那你的jvm分配的内存得够大
Exception in thread "main" java.lang.OutOfMemoryError
string存不下,
你看看这个吧!希望对你有帮助http://blog.csdn.net/mfx1986/article/details/5606228
Exception in thread "main" java.lang.OutOfMemoryError
当然可以你把JVM的内存扩大,前提是你有足够打的内存就可以加载。
Exception in thread "main" java.lang.OutOfMemoryError
个人认为,读超大容量的文件扩大内存不是很好的办法。
比如项目中,发现代码中有三维数组,不是说不可以,这肯定是设计的问题。
这是什么需求,楼主不妨说来听听。。
Exception in thread "main" java.lang.OutOfMemoryError
OutOfMemoryError
内存溢出- –
Exception in thread "main" java.lang.OutOfMemoryError
引用 5 楼 NNTT2010 的回复:

个人认为,读超大容量的文件扩大内存不是很好的办法。
比如项目中,发现代码中有三维数组,不是说不可以,这肯定是设计的问题。
这是什么需求,楼主不妨说来听听。。

我想用lucene做对这些txt文档实现搜索并返回搜索内容,这必须要将txt文档保存到索引中,所以我要讲300M的txt文档读成string类型,但是这个不能实现,不知道要怎么实现。

Exception in thread "main" java.lang.OutOfMemoryError
1、这是可行的;前提是java的内存设置够大。String类型可以支持最大到2G的文件。
2、这是没必要的;这样开销太大,建议重新设计。
Exception in thread "main" java.lang.OutOfMemoryError
楼主你说你要把文档内容转换到String里面再存储。这是不必要的。lucene的提供了

 public Field(String name, Reader reader)

这个方法,也就是说,你不用考虑将一个文件转换为string,只要传入Reader对象就可以了。然后再讲Field对象存放在Document里就ok了。

Exception in thread "main" java.lang.OutOfMemoryError
引用 9 楼 NNTT2010 的回复:

楼主你说你要把文档内容转换到String里面再存储。这是不必要的。lucene的提供了
Java code?1 public Field(String name, Reader reader)
这个方法,也就是说,你不用考虑将一个文件转换为string,只要传入Reader对象就可以了。然后再讲Field对象存放在Document里就ok了。

lucene提供的这个方法我也试过了,文件传入Reader对象,然后再讲Field对象存放在Document里,这里对文件内容是不存储的,如下:
Field(String name, Reader reader) 
     Create a tokenized and indexed field that is not stored.
不存储的话我最后搜索完之后就不能返回文档中我搜索的内容了。
请问我要怎么实现呢?

Exception in thread "main" java.lang.OutOfMemoryError
额,楼主你用lucene来创建索引。最终是返回存储内容是吗?
我想问下,你这个文件是什么样的?小说,还是想map中key和value对应的那种数据?你想返回关键字在哪一行还是其他?
Exception in thread "main" java.lang.OutOfMemoryError
引用 11 楼 NNTT2010 的回复:

额,楼主你用lucene来创建索引。最终是返回存储内容是吗?
我想问下,你这个文件是什么样的?小说,还是想map中key和value对应的那种数据?你想返回关键字在哪一行还是其他?

嗯,是想返回存储文档的内容。我的数据如下所示:
420 01143000024919 01143000025919 1.0
420 01143000027126 01143000028142 1.0
419 01143000034465 01143000035465 1.0
418 01143000035872 01143000036872 1.0
419 01143000036277 01143000037287 1.0
416 01143000038867 01143000039867 1.0
416 01143000040725 01143000041748 1.0
……………………
……………………
很多很多,整个txt文档有300M左右,一共有五六个txt文档,我想实现的功能就是搜索时输入关键字,比如我输入420,它能返回给我
420 01143000024919 01143000025919 1.0
420 01143000027126 01143000028142 1.0
就是将包含420的那一行数据都返回给我。
这就是我为什么要对搜索的内容进行存储的原因,如果我不存储,就不能返回给我数据,可是五六个这么大的txt文档实在太大,就算实现存储感觉消耗也很大。是否有其他方法,比如返回我搜索的420在文档中的位置信息,然后我再通过这个位置信息直接打开文档查找等,不知这样是否可行?我现在刚开始学lucene,对它的研究还只是停留在很表面的层次,多谢您了~~

Exception in thread "main" java.lang.OutOfMemoryError
额,原来是这样。那可以这样,先将这个300M+的文件拆分,并建立索引,然后只要这些索引中查找关键字就可以了。
Exception in thread "main" java.lang.OutOfMemoryError
楼主我想了一下,上网搜了一下,发现其有还有很多方法可以实现的。比如

public static void main(String[] args) throws Exception {
    int bufSize = 1024;
    byte[] bs = new byte[bufSize];
    // 这里是分配缓存大小。也就是用来存放从硬盘中度出来的文件
    // 什么叫一次把文件读出来?其实就是当缓存大小和在硬盘中文件大小一样,
    // 只通过一个read指令把整个文件都扔到缓存里面。例如要一次读一个2G的文件,把缓存设为2G就能一次读出来。
    // 不过当分配空间的时候,这个缓存根本是分配不出来的,因为内存不足。
    ByteBuffer byteBuf = ByteBuffer.allocate(bufSize);
    FileChannel channel = new RandomAccessFile("d:\filename","r").getChannel();
    int size;
    // 因为这里缓存大小是1K,所以每个channel.read()指令最多只会读到文件的1K的内容。
    // 如果文件有1M大小,这里for会循环1024次,把文件分开1024次读取出来
    while((size = channel.read(byteBuf)) != -1) {
      byteBuf.rewind();
      byteBuf.get(bs);
      // 把文件当字符串处理,直接打印做为一个例子。
      System.out.print(new String(bs, 0, size));
      byteBuf.clear();
      //在这里可以执行lucene创索引的操作
    }
    channel.close();
  }
Exception in thread "main" java.lang.OutOfMemoryError
引用 14 楼 NNTT2010 的回复:

楼主我想了一下,上网搜了一下,发现其有还有很多方法可以实现的。比如

Java code?12345678910111213141516171819202122public static void main(String[] args) throws Exception {    int bufSize = 1024;    byte[] bs = new byte[……

非常感谢您提供的这个办法,我照着试了一下,真的把我的所有数据都能读出来了,可是我在lucene建立索引的时候又遇到了一点新的问题,不知道您能不能再指导一下:

 while((size = channel.read(byteBuf)) != -1) {
      byteBuf.rewind();
      byteBuf.get(bs);
      // 把文件当字符串处理,直接打印做为一个例子。
      System.out.print(new String(bs, 0, size));
      byteBuf.clear();
      //在这里可以执行lucene创索引的操作
    }

就是在上面这个while循环里添加lucene索引操作的话,就相当于对于我每次读出来的1k内容进行索引,那我每次循环建立的索引就会把前面的索引覆盖了,有什么办法可以不让出现覆盖而且把这些内容建立在一个索引中呢?

Exception in thread "main" java.lang.OutOfMemoryError
引用 15 楼 sdf11179 的回复:

引用 14 楼 NNTT2010 的回复:楼主我想了一下,上网搜了一下,发现其有还有很多方法可以实现的。比如

Java code?12345678910111213141516171819202122public static void main(String[] args) throws Exception {    int bufSize = 1024;    ……

我大概试了一下,的确存在覆盖索引的问题。我这里的数据比较小
我先声明一个全局String content
 while((size = channel.read(byteBuf)) != -1) {
      byteBuf.rewind();
      byteBuf.get(bs);
      // 把文件当字符串处理,直接打印做为一个例子。
      System.out.print(new String(bs, 0, size));
      byteBuf.clear();
      //在这里可以执行lucene创索引的操作
     // 我在这里content += new String(bs, 0, size)
    }
最后我将content(就是整个内容)做一个创建索引。
还是回到老问题了,其实。你的可能在读文件的时候,一下子放到内存里,导致内存不足。
你再试试吧。

Exception in thread "main" java.lang.OutOfMemoryError
300M的记事本应该存的并不是单纯的文本信息吧。。
还是建议用别的方式来存储。。
Exception in thread "main" java.lang.OutOfMemoryError
我试了一下。
while((size = channel.read(byteBuf)) != -1) {
      byteBuf.rewind();
      byteBuf.get(bs);
      // 把文件当字符串处理,直接打印做为一个例子。
      System.out.print(new String(bs, 0, size));
      byteBuf.clear();
      //在这里可以执行lucene创索引的操作
     //这里每次new一个Document对象,然后add一个field都不会覆盖的啊。
    }
Exception in thread "main" java.lang.OutOfMemoryError
20分
一开始我是把Document作为一个全局变量,然后也出现覆盖,放到while循环里就不会覆盖了,楼主试试。
Exception in thread "main" java.lang.OutOfMemoryError
引用 19 楼 NNTT2010 的回复:

一开始我是把Document作为一个全局变量,然后也出现覆盖,放到while循环里就不会覆盖了,楼主试试。

我按这个思路试了试,真的实现了,非常感谢您一直帮助我,真的很感激~~希望以后我有问题时还能向您请教,谢谢了~~

Exception in thread "main" java.lang.OutOfMemoryError
引用 20 楼 sdf11179 的回复:

引用 19 楼 NNTT2010 的回复:一开始我是把Document作为一个全局变量,然后也出现覆盖,放到while循环里就不会覆盖了,楼主试试。
我按这个思路试了试,真的实现了,非常感谢您一直帮助我,真的很感激~~希望以后我有问题时还能向您请教,谢谢了~~

呵呵,别这么说,我自己也学到了一点东西。。加油楼主!

Exception in thread "main" java.lang.OutOfMemoryError
这个问题其实最好的解决方式是,解析出来之后放到key-value内存数据库中

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明Exception in thread "main" java.lang.OutOfMemoryError
喜欢 (0)
[1034331897@qq.com]
分享 (0)

文章评论已关闭!