2011-12-14 40 views
3

我有wiki.txt文件,其大小为50 MB。将文本文件加载到Java中的内存

  1. 我需要在文件上做几件事情,所以我认为性能方面的最佳方式是将文件加载到内存中,是否正确?

  2. 这是我写的代码:

    File file = new File("wiki.txt"); 
    FileInputStream fileInputStream = new FileInputStream(file); 
    FileChannel fileChannel = fileInputStream.getChannel(); 
    MappedByteBuffer mapByteBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, file.length()); 
    System.out.println((char)mapByteBuffer.get()); 
    

我对这个代码得到错误:mapByteBuffer.get()。 我尝试了get()函数几个选项,但所有他们我得到的错误,甚至没有在e.getMessage()我得到了一个错误。

另一个重要的事情要注意,我的文本文件包含英语单词和我需要做的动作是搜索,如果表达存在这个文本文件。

谢谢。

+2

你会得到哪个错误? – bvd 2011-12-14 07:45:52

+0

请发布您收到的错误消息。此外,从文本文件中查看一些样本行会有所帮助 - 然后我们可以提出一种有效的方式来阅读和存储它(您显示的代码背后严重缺乏理解)。 – 2011-12-14 07:59:10

回答

3

我会建议使用MemoryMappedFile,直接从磁盘读取文件,而不是将其加载到内存中。

RandomAccessFile file = new RandomAccessFile("wiki.txt", "r"); 
FileChannel channel = file.getChannel(); 
MappedByteBuffer buf = channel.map(FileChannel.MapMode.READ_WRITE, 0, 1024*50); 

然后你就可以读取缓冲区如常。

1

我会建议使用BufferedReader。它速度更快,所需资源相对较少。线 首先阅读数:

InputStream is = new BufferedInputStream(new FileInputStream(filename)); 
byte[] chars = new byte[1024]; 
int numberOfChars = 0; 
while ((numberOfChars = is.read(chars)) != -1) 
{ 
    for (int i = 0; i < numberOfChars; ++i) 
    { 
     if (chars[i] == '\n' && numberOfChars - i != 1) 
     { 
      ++count; 
     }   
    } 
} 
count++ 
return count; // number of lines 

然后读线:

BufferedReader in = new BufferedReader(new FileReader(fileName)); 
for (int i = 0; i < endLine; i++) 
{ 
    String oneLine = in.readLine(); 
} 

在这个字符串,你甚至可以搜索您所需要的。

+0

但是我需要回顾一下几种不同的表达方式,当我再次浏览整个文件时,真的会更好吗? – 2011-12-14 16:31:36

+0

不是一个好主意。 如果我的字符串在50MB文件的末尾,所以这需要很长时间。 – 2011-12-15 07:47:59

2

我的回答对点(1):

这取决于你想用文件做什么。如果您的处理不涉及倒带操作(查看后面/之前读取的内容),最好只读取流并一次处理它(而不是全部加载到内存中)。

即使您需要跨文件进行随机访问,也可能对块文件操作感兴趣,因为当文件大小变为较大时,解决方案可能无法很好地扩展。 RandomAccessFile如果您使用Java 1.4或更高版本。 对于随机访问,操作系统通常会很好地处理文件缓冲区缓存,您不必自己处理。

2

重要的是要读取整个错误,而不仅仅是消息。通常情况下,真实的信息是以例外的名称而不是与其相关的文本。

如果由于没有第一个字节而导致文件为空,您将会收到错误。

注意:您使用的方法采用ASCII 7位字符。如果你想假设ISO-8859-1字符,你可以使用(char) (byteBuffer.get() & 0xFF)

但是,如果你有计划文本,你可能会发现使用字符串更简单,使用起来并不慢。例如您可以在不到一秒的时间内以文本形式读取50 MB文件。如果这太长,我只会使用内存映射文件。

相关问题