這篇文章將描述怎樣在JAVA中高效的讀取一個大文件html
咱們通常經常使用的方法是在內存中讀取文件。—包括 Guava 和 Apache Commons IO 都提供了一個簡便的方法來操做:java
Files.readLines(new File(path), Charsets.UTF_8); FileUtils.readLines(new File(path));
這是會發生問題的,咱們將全部的文件都保存在了內存中。要是文件過大,就會出現 OutOfMemoryError ;ui
例如,讀取1個1GB的文件code
@Test public void givenUsingGuava_whenIteratingAFile_thenWorks() throws IOException { String path = ... Files.readLines(new File(path), Charsets.UTF_8); }
內存會被耗盡htm
[main] INFO org.baeldung.java.CoreJavaIoUnitTest - Total Memory: 128 Mb
[main] INFO org.baeldung.java.CoreJavaIoUnitTest - Free Memory: 116 Mbip
在咱們讀取完文件操做後。咱們能夠看到內存:內存
[main] INFO org.baeldung.java.CoreJavaIoUnitTest - Total Memory: 2666 Mb
[main] INFO org.baeldung.java.CoreJavaIoUnitTest - Free Memory: 490 Mb開發
這意味着。有2.1GB的內存被使用,緣由很簡單,就是把全部文件都裝入了內存input
但一般。咱們並不須要一次性加載內存中的全部文件。咱們僅僅須要遍歷文件。作一些操做。而後丟棄。因此,咱們如今要作的就是不把文件徹底加入到內存中依次遍歷文件。it
咱們來看看這個方法。咱們將經過 java.util.Scanner 來依次遍歷。
FileInputStream inputStream = null; Scanner sc = null; try { inputStream = new FileInputStream(path); sc = new Scanner(inputStream, "UTF-8"); while (sc.hasNextLine()) { String line = sc.nextLine(); // System.out.println(line); } // note that Scanner suppresses exceptions if (sc.ioException() != null) { throw sc.ioException(); } } finally { if (inputStream != null) { inputStream.close(); } if (sc != null) { sc.close(); } }
這個方法,依次遍歷文件,對每行文件均可以處理。而且不須要所有加載在內存中
[main] INFO org.baeldung.java.CoreJavaIoUnitTest - Total Memory: 763 Mb
[main] INFO org.baeldung.java.CoreJavaIoUnitTest - Free Memory: 605 Mb
上面的那個操做也能夠經過 Commons IO 來實現每一行的遍歷
LineIterator it = FileUtils.lineIterator(theFile, "UTF-8"); try { while (it.hasNext()) { String line = it.nextLine(); // do something with line } } finally { LineIterator.closeQuietly(it); }
一樣,也是不在內存中加載所有文件。少許的內存消耗:
[main] INFO o.b.java.CoreJavaIoIntegrationTest - Total Memory: 752 Mb
[main] INFO o.b.java.CoreJavaIoIntegrationTest - Free Memory: 564 Mb
好了,文章到此結束,在咱們平常的開發中,在遇到讀取大文件就能夠參照以上的方法了。