Alle bisher gegebenen Antworten beinhalten das zeilenweise Lesen der Datei, das Aufnehmen der Zeile als String
und das anschließende Verarbeiten der String
.
Es steht außer Frage, dass dies der am einfachsten zu verstehende Ansatz ist. Wenn die Datei ziemlich kurz ist (z. B. Zehntausende von Zeilen), ist sie auch im Hinblick auf die Effizienz akzeptabel. Wenn die Datei jedoch lang ist , ist dies aus zwei Gründen eine sehr ineffiziente Methode:
- Jedes Zeichen wird zweimal verarbeitet, einmal beim Erstellen des
String
und einmal beim Verarbeiten.
- Der Garbage Collector ist nicht Ihr Freund, wenn die Datei viele Zeilen enthält. Sie erstellen
String
für jede Zeile eine neue und werfen sie dann weg, wenn Sie zur nächsten Zeile wechseln. Der Garbage Collector muss schließlich alle diese String
Objekte entsorgen , die Sie nicht mehr benötigen. Jemand muss nach dir aufräumen.
Wenn Sie Wert auf Geschwindigkeit legen, ist es viel besser, einen Datenblock zu lesen und ihn dann byteweise zu verarbeiten, als zeilenweise. Jedes Mal , wenn Sie an das Ende einer Reihe kommen, fügen Sie es auf die List
Sie bauen.
Es wird ungefähr so herauskommen:
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;
}
Der obige Code geht davon aus, dass dies ASCII ist (obwohl es für andere Codierungen leicht angepasst werden kann) und dass alles, was keine Ziffer ist (insbesondere ein Leerzeichen oder eine neue Zeile), eine Grenze zwischen Ziffern darstellt. Es wird auch davon ausgegangen, dass die Datei mit einer Nicht-Ziffer endet (in der Praxis endet die letzte Zeile mit einer neuen Zeile). Sie kann jedoch erneut angepasst werden, um den Fall zu behandeln, in dem dies nicht der Fall ist.
Es ist viel, viel schneller als jeder der String
basierten Ansätze, die auch als Antwort auf diese Frage gegeben werden. Es gibt eine detaillierte Untersuchung eines sehr ähnlichen Themas in dieser Frage . Sie werden dort sehen, dass es die Möglichkeit gibt, es noch weiter zu verbessern, wenn Sie die Multithread-Linie durchlaufen möchten.