{"id":1508,"date":"2014-01-15T09:25:19","date_gmt":"2014-01-15T14:25:19","guid":{"rendered":"http:\/\/alejandroayala.solmedia.ec\/?p=1508"},"modified":"2014-01-15T09:29:54","modified_gmt":"2014-01-15T14:29:54","slug":"java-leer-archivos-grandes-eficientemente","status":"publish","type":"post","link":"https:\/\/alejandroayala.solmedia.ec\/?p=1508","title":{"rendered":"Java. Leer archivos grandes eficientemente."},"content":{"rendered":"<h2 style=\"text-align: justify;\">Introducci\u00f3n<\/h2>\n<p style=\"text-align: justify;\">Este tutorial mostrar\u00e1 como leer un archivo bastante pesado(largo) de una manera eficiente.<\/p>\n<h2 style=\"text-align: justify;\">Leyendo en memoria<\/h2>\n<p style=\"text-align: justify;\">La forma est\u00e1ndar de leer las l\u00edneas de un archivo es en memoria, ambas librer\u00edas <a href=\"http:\/\/code.google.com\/p\/guava-libraries\/\" target=\"_blank\"><em>Guava<\/em> <\/a>y <a href=\"https:\/\/commons.apache.org\/\" target=\"_blank\"><em>Apache Commons<\/em> <\/a>realizan esta tarea de una manera muy sencilla:<\/p>\n<p style=\"text-align: justify;\"><!--more--><\/p>\n<p>[java]<br \/>\nFiles.readLines(new File(path), Charsets.UTF_8);[\/java]<\/p>\n<p>[java]<br \/>\nFileUtils.readLines(new File(path));<br \/>\n[\/java]<\/p>\n<p style=\"text-align: justify;\">El problema con este enfoque es que todas las l\u00edneas son mantenidas en memoria, <strong>lo cual provocar\u00e1 f\u00e1cilmente un error<\/strong> <a href=\"http:\/\/download.oracle.com\/javase\/6\/docs\/api\/java\/lang\/OutOfMemoryError.html\" target=\"_blank\"><em><strong>OutOfMemoryError<\/strong> <\/em><\/a>si el archivo es demasiado grande.<\/p>\n<p style=\"text-align: justify;\">Por ejemplo al leer un archivo de 1Gb:<\/p>\n<p>[java]<br \/>\n@Test<br \/>\npublic void givenUsingGuava_whenIteratingAFile_thenWorks()<br \/>\n    throws IOException {<br \/>\n    String path = &#8230;<br \/>\n    Files.readLines(new File(path), Charsets.UTF_8);<br \/>\n}<br \/>\n[\/java]<\/p>\n<p style=\"text-align: justify;\">Al inicio empieza con peque\u00f1o consumo de memoria:<\/p>\n<p>[bash]<br \/>\n[main] INFO  org.baeldung.java.CoreJavaIoUnitTest &#8211; Total Memory: 128 Mb<br \/>\n[main] INFO  org.baeldung.java.CoreJavaIoUnitTest &#8211; Free Memory: 116 Mb<br \/>\n[\/bash]<\/p>\n<p style=\"text-align: justify;\">Sin embargo, luego de que todo el archivo ha sido procesado:<\/p>\n<p>[bash]<br \/>\n[main] INFO  org.baeldung.java.CoreJavaIoUnitTest &#8211; Total Memory: 2666 Mb<br \/>\n[main] INFO  org.baeldung.java.CoreJavaIoUnitTest &#8211; Free Memory: 490 Mb<br \/>\n[\/bash]<\/p>\n<p style=\"text-align: justify;\">Lo que significa que alrededor <strong>de 2.1 Gb de memoria son consumidas por el proceso<\/strong> \u2013 la raz\u00f3n es simple \u2013 ahora todas las lineas del archivo est\u00e1n almacenadas en memoria.<\/p>\n<p style=\"text-align: justify;\">Parece obvio que al mantener en memoria todo el contenido del archivo, <strong>agotar\u00e1 r\u00e1pidamente la memoria disponible<\/strong>, aunque dispongamos de mucha memoria.<\/p>\n<p style=\"text-align: justify;\">De echo, nosotros no necesitamos tener todas las l\u00edneas del fichero cargadas en memoria, en su lugar, nosotros necesitamos poder ser capaces de <strong>recorrer l\u00ednea a l\u00ednea con algo de procesamiento y luego desecharlo<\/strong>. Eso es lo que vamos ha hacer, iterar por cada l\u00ednea sin tener la necesidad de almacenarlo en memoria.<\/p>\n<h2 style=\"text-align: justify;\">Haciendo \u00abStreaming\u00bb por el archivo<\/h2>\n<p style=\"text-align: justify;\">Tomen en cuenta la soluci\u00f3n, vamos a usar la clase <a href=\"http:\/\/download.oracle.com\/javase\/6\/docs\/api\/java\/util\/Scanner.html\" target=\"_blank\"><em><strong>java.util.Scanner<\/strong><\/em><\/a> para correr por el contenido del archivo para recuperar las l\u00edneas en serie, una a una:<\/p>\n<p>[java]<br \/>\nFileInputStream inputStream = null;<br \/>\nScanner sc = null;<br \/>\ntry {<br \/>\n    inputStream = new FileInputStream(path);<br \/>\n    sc = new Scanner(inputStream, &quot;UTF-8&quot;);<br \/>\n    while (sc.hasNextLine()) {<br \/>\n        String line = sc.nextLine();<br \/>\n        \/\/ System.out.println(line);<br \/>\n    }<br \/>\n    \/\/ note that Scanner suppresses exceptions<br \/>\n    if (sc.ioException() != null) {<br \/>\n        throw sc.ioException();<br \/>\n    }<br \/>\n} finally {<br \/>\n    if (inputStream != null) {<br \/>\n        inputStream.close();<br \/>\n    }<br \/>\n    if (sc != null) {<br \/>\n        sc.close();<br \/>\n    }<br \/>\n}<br \/>\n[\/java]<\/p>\n<p style=\"text-align: justify;\">Esta soluci\u00f3n itera a trav\u00e9s de todas las l\u00edneas en el archivo, permitiendo el procesamiento de cada l\u00ednea, sin mantener referencias a el, lo que quiere decir sin mantenerlo en memoria.<\/p>\n<h2 style=\"text-align: justify;\">Conclusi\u00f3n<\/h2>\n<p style=\"text-align: justify;\">Este peque\u00f1o art\u00edculo muestra como procesar l\u00edneas de un archivo grande sin agotar la memoria disponible, lo que resulta muy \u00fatil cuando se trabaja con este tipo de archivos.<\/p>\n<p>Fuente: <a href=\"http:\/\/www.baeldung.com\/java-read-lines-large-file\" target=\"_blank\">http:\/\/www.baeldung.com\/java-read-lines-large-file<\/a><\/p>\n\n<div class=\"twitter-share\"><a href=\"https:\/\/twitter.com\/intent\/tweet?via=a1ejo_ayala\" class=\"twitter-share-button\" data-size=\"large\">Twittear<\/a><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Introducci\u00f3n Este tutorial mostrar\u00e1 como leer un archivo bastante pesado(largo) de una manera eficiente. Leyendo en memoria La forma est\u00e1ndar de leer las l\u00edneas de un archivo es en memoria, ambas librer\u00edas Guava y Apache Commons realizan esta tarea de una manera muy sencilla:<\/p>\n","protected":false},"author":1,"featured_media":690,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0},"categories":[4],"tags":[426,425,506,427,388,428],"_links":{"self":[{"href":"https:\/\/alejandroayala.solmedia.ec\/index.php?rest_route=\/wp\/v2\/posts\/1508"}],"collection":[{"href":"https:\/\/alejandroayala.solmedia.ec\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/alejandroayala.solmedia.ec\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/alejandroayala.solmedia.ec\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/alejandroayala.solmedia.ec\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1508"}],"version-history":[{"count":4,"href":"https:\/\/alejandroayala.solmedia.ec\/index.php?rest_route=\/wp\/v2\/posts\/1508\/revisions"}],"predecessor-version":[{"id":1511,"href":"https:\/\/alejandroayala.solmedia.ec\/index.php?rest_route=\/wp\/v2\/posts\/1508\/revisions\/1511"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/alejandroayala.solmedia.ec\/index.php?rest_route=\/wp\/v2\/media\/690"}],"wp:attachment":[{"href":"https:\/\/alejandroayala.solmedia.ec\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1508"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/alejandroayala.solmedia.ec\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1508"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/alejandroayala.solmedia.ec\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1508"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}