Всі наведені досі відповіді включають читання файлу рядок за рядком, прийняття рядка як a String
, а потім обробкуString
.
Немає сумнівів, що це найпростіший для розуміння підхід, і якщо файл досить короткий (скажімо, десятки тисяч рядків), це також буде прийнятним з точки зору ефективності. Але якщо файл довгий , це дуже неефективний спосіб зробити це з двох причин:
- Кожен символ обробляється двічі, один раз при побудові
String
та один раз при його обробці.
- Збирач сміття не буде вашим другом, якщо у файлі багато рядків. Ви створюєте новий
String
для кожного рядка, а потім викидаєте його, коли переходите до наступного рядка. Збірщику сміття з часом доведеться утилізувати всі ці String
об’єкти, які вам більше не потрібні. Хтось повинен прибрати за вами.
Якщо ви дбаєте про швидкість, вам набагато краще прочитати блок даних, а потім обробити його байт за байтом, а не рядок за рядком. Щоразу, коли ви закінчуєте число, ви додаєте його доList
ви будуєте.
Вийде приблизно так:
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;
}
Наведений вище код передбачає, що це ASCII (хоча його можна легко налаштувати для інших кодувань), і що все, що не є цифрою (зокрема, пробіл або новий рядок), представляє межу між цифрами. Він також припускає, що файл закінчується нецифровим числом (на практиці останній рядок закінчується новим рядком), хоча, знову ж таки, його можна налаштувати для вирішення справи, коли він цього не робить.
Це набагато, набагато швидше, ніж будь-який з String
підходів, що базуються також на відповідях на це питання. У цьому питанні детально розслідується дуже схоже питання . Ви побачите там, що існує можливість його вдосконалення ще більше, якщо ви хочете спуститись по багатопотоковій лінії.