Todas las respuestas dadas hasta ahora implican leer el archivo línea por línea, tomar la línea como a String
, y luego procesar el String
.
No hay duda de que este es el enfoque más fácil de entender, y si el archivo es bastante corto (digamos, decenas de miles de líneas), también será aceptable en términos de eficiencia. Pero si el archivo es largo , es una forma muy ineficiente de hacerlo, por dos razones:
- Cada personaje se procesa dos veces, una al construir
String
y otra al procesarlo.
- El recolector de basura no será su amigo si hay muchas líneas en el archivo. Estás construyendo una nueva
String
para cada línea y luego la tiras cuando pasas a la siguiente línea. El recolector de basura eventualmente tendrá que deshacerse de todos estos String
objetos que usted ya no quiere. Alguien tiene que limpiar después de ti.
Si le importa la velocidad, es mucho mejor leer un bloque de datos y luego procesarlo byte por byte en lugar de línea por línea. Cada vez que llega al final de un número, lo agrega al List
que está construyendo.
Saldrá algo como esto:
private List<Integer> readIntegers(File file) throws IOException {
List<Integer> result = new ArrayList<>();
RandomAccessFile raf = new RandomAccessFile(file, "r");
byte buf[] = new byte[16 * 1024];
final FileChannel ch = raf.getChannel();
int fileLength = (int) ch.size();
final MappedByteBuffer mb = ch.map(FileChannel.MapMode.READ_ONLY, 0,
fileLength);
int acc = 0;
while (mb.hasRemaining()) {
int len = Math.min(mb.remaining(), buf.length);
mb.get(buf, 0, len);
for (int i = 0; i < len; i++)
if ((buf[i] >= 48) && (buf[i] <= 57))
acc = acc * 10 + buf[i] - 48;
else {
result.add(acc);
acc = 0;
}
}
ch.close();
raf.close();
return result;
}
El código anterior asume que esto es ASCII (aunque podría modificarse fácilmente para otras codificaciones) y que cualquier cosa que no sea un dígito (en particular, un espacio o una nueva línea) representa un límite entre dígitos. También asume que el archivo termina con un no dígito (en la práctica, que la última línea termina con una nueva línea), aunque, nuevamente, podría modificarse para tratar el caso donde no lo hace.
Es mucho, mucho más rápido que cualquiera de los String
enfoques basados también en respuestas a esta pregunta. Hay una investigación detallada de un tema muy similar en esta pregunta . Verá allí que existe la posibilidad de mejorarlo aún más si desea bajar por la línea de subprocesos múltiples.