1. Visão geral
Este tutorial demonstrará como ler com eficiência arquivos grandes em Java. Java - retorne ao básico.
2. Leia na memória
A maneira padrão de ler linhas de arquivo é ler na memória. Tanto a goiaba quanto a apacheCommonsio fornecem métodos para ler rapidamente as linhas de arquivo da seguinte forma:
Files.readLines(new File(path), Charsets.UTF_8);
FileUtils.readLines(new File(path));
O problema com esse método é que todas as linhas do arquivo são armazenadas na memória e, quando o arquivo é grande o suficiente, ele rapidamente fará com que o programa jogue uma exceção ou exceção do MemoryError.
Por exemplo: Leia um arquivo de cerca de 1G:
@Testpublic void devidoundingguava_wheniteratingafile_thenworks () lança ioexception {string path = ... files.readLines (novo arquivo (path), charsets.utf_8);}Este método ocupa apenas uma pequena quantidade de memória no início: (consome cerca de 0 MB de memória)
[Principal] Info org.baeldung.java.corejavaiounittest - Memória total: 128 MB [principal] info org.baeldung.java.corejavaiounittest - Memória livre: 116 MB
No entanto, quando todos os arquivos são lidos na memória, podemos finalmente ver (cerca de 2 GB de memória é consumida):
[Principal] Info org.baeldung.java.corejavaiounittest - Memória total: 2666 MB [principal] info org.baeldung.java.corejavaiounittest - Memória livre: 490 MB
Isso significa que esse processo consome cerca de 2,1 GB de memória - o motivo é simples: agora todas as linhas do arquivo são armazenadas na memória.
Colocar todo o conteúdo de um arquivo na memória ficará rapidamente sem memória disponível - não importa o tamanho da memória disponível real, isso é óbvio.
Além disso, geralmente não precisamos colocar todas as linhas do arquivo na memória de uma só vez - em vez disso, precisamos apenas percorrer cada linha do arquivo, depois fazer o processamento correspondente e jogá -lo fora após o processamento. Então, é exatamente isso que vamos fazer - iterar através de linhas, em vez de colocar todas as linhas na memória.
3. Fluxo de arquivo
Agora, vejamos esta solução - usaremos a classe java.util.scanner para digitalizar o conteúdo do arquivo e lê -lo continuamente alinhado por linha:
FileInputStream inputStream = null; scanner sc = null; tente {inputStream = new FileInputStream (caminho); sc = novo scanner (inputStream, "utf-8"); while (sc.hasnextLine ()) {string line = sc.NextLine (); // system.out.println (linha); } // Observe que o scanner suprime exceções if (sc.ioException ()! = null) {tiro sc.ioException (); }} finalmente {if (inputStream! = null) {inputStream.close (); } if (sc! = null) {sc.close (); }}Esta solução atravessará todas as linhas no arquivo - permitindo que cada linha seja processada sem manter uma referência a ele. De qualquer forma, eles não foram armazenados na memória: (cerca de 150 MB de memória foram consumidos)
[Main] Infoorg.baeldung.java.corejavaiounittest-totalmemory: 763MB
[Main] Infoorg.baeldung.java.corejavaiounittest-Freemory: 605 MB
4. ApacheCommonsio Stream
Você também pode usar a Biblioteca CommonSio para implementá -la, usando o LineIterator personalizado fornecido pela Biblioteca:
LineIterator it = fileUtils.lineIterator (thefile, "utf-8"); tente {while (it.hasnext ()) {string line = it.NextLine (); // Faça algo com linha}} finalmente {lineIterator.closequietly (it);}Como todo o arquivo não é armazenado na memória, isso leva a um consumo de memória bastante conservador: (cerca de 150 MB de memória é consumido)
[main] infoo.b.java.corejavaiointegrationtestest-totalmemory: 752MB
[main] infoo.b.java.corejavaiointegrationtest-freeMemory: 564MB
5. Conclusão
Este artigo curto descreve como processar arquivos grandes sem leitura e falta de memória repetidas - isso fornece uma solução útil para o processamento de arquivos grandes.
Todos esses exemplos são implementados e trechos de código disponíveis no meu projeto GitHub - este é um projeto baseado em eclipse, por isso deve ser facilmente importado e executado.
O exposto acima é todo o conteúdo deste artigo sobre leitura eficiente em Java de arquivos grandes. Espero que seja útil para todos. Amigos interessados podem continuar se referindo a outros tópicos relacionados neste site. Se houver alguma falha, deixe uma mensagem para apontá -la. Obrigado amigos pelo seu apoio para este site!