Wszystkie dotychczas podane odpowiedzi obejmują czytanie pliku wiersz po wierszu, przyjmując wiersz jako plik String
, a następnie przetworzenieString
.
Nie ma wątpliwości, że jest to najłatwiejsze do zrozumienia podejście, a jeśli plik jest dość krótki (powiedzmy, dziesiątki tysięcy wierszy), będzie również akceptowalny pod względem wydajności. Ale jeśli plik jest długi , jest to bardzo nieefektywny sposób z dwóch powodów:
- Każdy znak jest przetwarzany dwukrotnie, raz podczas konstruowania
String
i raz podczas przetwarzania.
- Odśmiecacz nie będzie twoim przyjacielem, jeśli w pliku jest dużo wierszy. Tworzysz nowy
String
dla każdego wiersza, a następnie odrzucasz go, gdy przechodzisz do następnego wiersza. W końcu odśmiecacz będzie musiał pozbyć się wszystkich tych String
obiektów, których już nie chcesz. Ktoś musi po tobie posprzątać.
Jeśli zależy Ci na szybkości, znacznie lepiej jest odczytać blok danych, a następnie przetwarzać go bajt po bajcie, a nie wiersz po wierszu. Za każdym razem, gdy zbliżasz się do końca liczby, dodajesz ją do List
budowanej liczby .
Wyjdzie coś takiego:
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;
}
Powyższy kod zakłada, że jest to ASCII (chociaż można go łatwo dostosować do innych kodowań) i że wszystko, co nie jest cyfrą (w szczególności spacja lub znak nowej linii) reprezentuje granicę między cyframi. Zakłada również, że plik kończy się cyfrą niecyfrową (w praktyce ostatnia linia kończy się znakiem nowej linii), chociaż ponownie można go zmodyfikować, aby poradzić sobie z przypadkiem, w którym tak się nie dzieje.
Jest to dużo, dużo szybsze niż którekolwiek z String
podejść opartych na zasadzie podanych również jako odpowiedzi na to pytanie. W tym pytaniu szczegółowo zbadano bardzo podobną kwestię . Zobaczysz tam, że istnieje możliwość dalszego ulepszenia, jeśli chcesz zejść w dół po linii wielowątkowej.