我想把一个300M的txt文档用java读取之后内容存到string中代码如下: FileInputStream fis = new FileInputStream(files[i]); Exception in thread “main” java.lang.OutOfMemoryError: Java heap space |
|
300m估计你记事本都打不开 内存够大的话这个方法存在可能,但是这样效率低下
|
|
300m的文件放进内存,那你的jvm分配的内存得够大
|
|
string存不下,
你看看这个吧!希望对你有帮助http://blog.csdn.net/mfx1986/article/details/5606228 |
|
当然可以你把JVM的内存扩大,前提是你有足够打的内存就可以加载。
|
|
个人认为,读超大容量的文件扩大内存不是很好的办法。
比如项目中,发现代码中有三维数组,不是说不可以,这肯定是设计的问题。 这是什么需求,楼主不妨说来听听。。 |
|
OutOfMemoryError
内存溢出- – |
|
我想用lucene做对这些txt文档实现搜索并返回搜索内容,这必须要将txt文档保存到索引中,所以我要讲300M的txt文档读成string类型,但是这个不能实现,不知道要怎么实现。 |
|
1、这是可行的;前提是java的内存设置够大。String类型可以支持最大到2G的文件。
2、这是没必要的;这样开销太大,建议重新设计。 |
|
楼主你说你要把文档内容转换到String里面再存储。这是不必要的。lucene的提供了
public Field(String name, Reader reader) 这个方法,也就是说,你不用考虑将一个文件转换为string,只要传入Reader对象就可以了。然后再讲Field对象存放在Document里就ok了。 |
|
lucene提供的这个方法我也试过了,文件传入Reader对象,然后再讲Field对象存放在Document里,这里对文件内容是不存储的,如下: |
|
额,楼主你用lucene来创建索引。最终是返回存储内容是吗?
我想问下,你这个文件是什么样的?小说,还是想map中key和value对应的那种数据?你想返回关键字在哪一行还是其他? |
|
嗯,是想返回存储文档的内容。我的数据如下所示: |
|
额,原来是这样。那可以这样,先将这个300M+的文件拆分,并建立索引,然后只要这些索引中查找关键字就可以了。
|
|
楼主我想了一下,上网搜了一下,发现其有还有很多方法可以实现的。比如
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(); } |
|
非常感谢您提供的这个办法,我照着试了一下,真的把我的所有数据都能读出来了,可是我在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内容进行索引,那我每次循环建立的索引就会把前面的索引覆盖了,有什么办法可以不让出现覆盖而且把这些内容建立在一个索引中呢? |
|
我大概试了一下,的确存在覆盖索引的问题。我这里的数据比较小 |
|
300M的记事本应该存的并不是单纯的文本信息吧。。
还是建议用别的方式来存储。。 |
|
我试了一下。
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都不会覆盖的啊。 } |
|
20分 |
一开始我是把Document作为一个全局变量,然后也出现覆盖,放到while循环里就不会覆盖了,楼主试试。
|
我按这个思路试了试,真的实现了,非常感谢您一直帮助我,真的很感激~~希望以后我有问题时还能向您请教,谢谢了~~ |
|
呵呵,别这么说,我自己也学到了一点东西。。加油楼主! |
|
这个问题其实最好的解决方式是,解析出来之后放到key-value内存数据库中
|