Эффективный способ прочитать файл и разобрать каждую строку
1179 просмотра
3 ответа
У меня есть текстовый файл следующего формата: каждая строка начинается со строки, за которой следует последовательность чисел. Каждая строка имеет неизвестную длину (неизвестное количество чисел, количество от 0 до 1000).
string_1 3 90 12 0 3
string_2 49 0 12 94 13 8 38 1 95 3
.......
string_n 9 43
После этого я должен обработать каждую строку handleLine
методом, который принимает два аргумента: имя строки и набор чисел ( см. Код ниже ).
Как прочитать файл и обработать каждую строку handleLine
эффективно?
Мой обходной путь:
- Читайте файл построчно с потоками java8
Files.lines
. Это блокирует? - Разделите каждую строку с помощью регулярного выражения
- Конвертировать каждую строку в строку заголовка и набор чисел
Я думаю, что это довольно неэффективно из-за 2-го и 3-го шагов. Первый шаг означает, что сначала java конвертирует байты файла в строку, а затем на втором и третьем шагах я конвертирую их обратно в String
/ Set<Integer>
. Это сильно влияет на производительность? Если да - как сделать лучше?
public handleFile(String filePath) {
try (Stream<String> stream = Files.lines(Paths.get(filePath))) {
stream.forEach(this::indexLine);
} catch (IOException e) {
e.printStackTrace();
}
}
private void handleLine(String line) {
List<String> resultList = this.parse(line);
String string_i = resultList.remove(0);
Set<Integer> numbers = resultList.stream().map(Integer::valueOf).collect(Collectors.toSet());
handleLine(string_i, numbers); // Here is te final computation which must to be done only with string_i & numbers arguments
}
private List<String> parse(String str) {
List<String> output = new LinkedList<String>();
Matcher match = Pattern.compile("[0-9]+|[a-z]+|[A-Z]+").matcher(str);
while (match.find()) {
output.add(match.group());
}
return output;
}
Автор: VB_
Источник
Размещён: 12.11.2019 09:03
Ответы (3)
3 плюса
Что касается вашего первого вопроса, это зависит от того, как вы ссылаетесь на Stream
. Streams
по своей природе ленивы и не выполняют работу, если не собираетесь ее использовать. Например, вызов Files.lines
фактически не читает файл, пока вы не добавите терминальную операцию в Stream
.
Из документа Java:
Читать все строки из файла как поток. В отличие от readAllLines, этот метод не читает все строки в List, а вместо этого заполняет их лениво по мере использования потока.
forEach(Consumer<T>)
Вызов терминала операция, и, в этой точке, то строки файла считываются по одному и переданы вашему indexLine
методу.
Что касается ваших других комментариев, у вас действительно нет вопроса здесь. Что вы пытаетесь измерить / минимизировать? Тот факт, что что-то состоит из нескольких шагов, по своей сути не делает его плохим. Даже если вы создали welbang oneliner для преобразования File
байтов непосредственно в ваш String
& Set
, вы, вероятно, просто сделали промежуточное отображение анонимно, или вы вызвали что-то, что заставит компилятор сделать это в любом случае.
1 плюс
Вот ваш код для разбора строки на имя и цифры
stream.forEach(line -> {
String[] split = line.split("\\b"); //split with blank seperator
Set<String> numbers = IntStream.range(1, split.length)
.mapToObj(index -> split[index])
.filter(str -> str.matches("\\d+")) //filter numbers
.collect(Collectors.toSet());
handleLine(split[0], numbers);
});
Или другой способ
Map<Boolean, List<String>> collect = Pattern.compile("\\b")
.splitAsStream(line)
.filter(str -> !str.matches("\\b"))
.collect(Collectors.groupingBy(str -> str.matches("\\d+")));
handleLine(collect.get(Boolean.FALSE).get(0), collect.get(Boolean.TRUE));
Автор: M S
Размещён: 24.10.2016 09:14
1 плюс
Я решил протестировать несколько способов решения этой проблемы и измерить производительность как можно лучше в указанных условиях. Вот что я проверял и как я это проверял вместе с сопровождающими результатами:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.Scanner;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
public class App {
public static void method1(String testFile) {
List<Integer> nums = null;
try (Scanner s = new Scanner(Paths.get(testFile))) {
while (s.hasNext()) {
if (s.hasNextInt())
nums.add(s.nextInt());
else {
nums = new ArrayList<Integer>();
String pre = s.next();
// handleLine( s.next() ... nums ... );
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void method2(String testFile) {
List<Integer> nums = null;
try (BufferedReader in = new BufferedReader(new FileReader(testFile));
Scanner s = new Scanner(in)) {
while (s.hasNext()) {
if (s.hasNextInt())
nums.add(s.nextInt());
else {
nums = new ArrayList<Integer>();
String pre = s.next();
// handleLine( s.next() ... nums ... );
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void method3(String testFile) {
List<Integer> nums = null;
try (BufferedReader br = new BufferedReader(new FileReader(testFile))) {
String line = null;
while ((line = br.readLine()) != null) {
String[] arr = line.split(" ");
nums = new ArrayList<Integer>();
for (int i = 1; i < arr.length; ++i)
nums.add(Integer.valueOf(arr[i]));
// handleLine( ... );
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void method3_1(String testFile) {
List<Integer> nums = null;
try (BufferedReader br = new BufferedReader(new FileReader(testFile))) {
String line = null;
while ((line = br.readLine()) != null) {
String[] arr = line.split(" ");
nums = new ArrayList<Integer>();
for (int i = 1; i < arr.length; ++i)
nums.add(Integer.parseInt(arr[i]));
// handleLine( ... );
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void method4(String testFile) {
List<Integer> nums = null;
try {
List<String> lines = Files.readAllLines(Paths.get(testFile));
for (String s : lines) {
String[] arr = s.split(" ");
nums = new ArrayList<Integer>();
for (int i = 1; i < arr.length; ++i)
nums.add(Integer.valueOf(arr[i]));
// handleLine( ... );
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void method4_1(String testFile) {
List<Integer> nums = null;
try {
List<String> lines = Files.readAllLines(Paths.get(testFile));
for (String s : lines) {
String[] arr = s.split(" ");
nums = new ArrayList<Integer>();
for (int i = 1; i < arr.length; ++i)
nums.add(Integer.parseInt(arr[i]));
// handleLine( ... );
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void method5(String testFile) {
List<Integer> nums = null;
try (BufferedReader br = Files.newBufferedReader(Paths.get(testFile))) {
List<String> lines = br.lines().collect(Collectors.toList());
for (String s : lines) {
String[] arr = s.split(" ");
nums = new ArrayList<Integer>();
for (int i = 1; i < arr.length; ++i)
nums.add(Integer.valueOf(arr[i]));
// handleLine( ... );
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void method5_1(String testFile) {
List<Integer> nums = null;
try (BufferedReader br = Files.newBufferedReader(Paths.get(testFile))) {
List<String> lines = br.lines().collect(Collectors.toList());
for (String s : lines) {
String[] arr = s.split(" ");
nums = new ArrayList<Integer>();
for (int i = 1; i < arr.length; ++i)
nums.add(Integer.parseInt(arr[i]));
// handleLine( ... );
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void method6(String testFile) {
List<Integer> nums = new LinkedList<Integer>();
try (Stream<String> stream = Files.lines(Paths.get(testFile))) {
stream.forEach(line -> {
String[] split = line.split("\\b"); // split with blank seperator
Set<String> numbers = IntStream.range(1, split.length)
.mapToObj(index -> split[index])
.filter(str -> str.matches("\\d+")) // filter numbers
.collect(Collectors.toSet());
numbers.forEach((k) -> nums.add(Integer.parseInt(k)));
// handleLine( ... );
});
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
args = new String[] { "C:\\Users\\Nick\\Desktop\\test.txt" };
Random r = new Random();
System.out.println("warming up a little...");
for (int i = 0; i < 100000; ++i) {
int x = r.nextInt();
}
long s1 = System.currentTimeMillis();
for (int i = 0; i < 10000; ++i)
method1(args[0]);
long e1 = System.currentTimeMillis();
long s2 = System.currentTimeMillis();
for (int i = 0; i < 10000; ++i)
method2(args[0]);
long e2 = System.currentTimeMillis();
long s3 = System.currentTimeMillis();
for (int i = 0; i < 10000; ++i)
method3(args[0]);
long e3 = System.currentTimeMillis();
long s3_1 = System.currentTimeMillis();
for (int i = 0; i < 10000; ++i)
method3_1(args[0]);
long e3_1 = System.currentTimeMillis();
long s4 = System.currentTimeMillis();
for (int i = 0; i < 10000; ++i)
method4(args[0]);
long e4 = System.currentTimeMillis();
long s4_1 = System.currentTimeMillis();
for (int i = 0; i < 10000; ++i)
method4_1(args[0]);
long e4_1 = System.currentTimeMillis();
long s5 = System.currentTimeMillis();
for (int i = 0; i < 10000; ++i)
method5(args[0]);
long e5 = System.currentTimeMillis();
long s5_1 = System.currentTimeMillis();
for (int i = 0; i < 10000; ++i)
method5_1(args[0]);
long e5_1 = System.currentTimeMillis();
long s6 = System.currentTimeMillis();
for (int i = 0; i < 10000; ++i)
method6(args[0]);
long e6 = System.currentTimeMillis();
System.out.println("method 1 = " + (e1 - s1) + " ms");
System.out.println("method 2 = " + (e2 - s2) + " ms");
System.out.println("method 3 = " + (e3 - s3) + " ms");
System.out.println("method 3_1 = " + (e3_1 - s3_1) + " ms");
System.out.println("method 4 = " + (e4 - s4) + " ms");
System.out.println("method 4_1 = " + (e4_1 - s4_1) + " ms");
System.out.println("method 5 = " + (e5 - s5) + " ms");
System.out.println("method 5_1 = " + (e5_1 - s5_1) + " ms");
System.out.println("method 6 = " + (e6 - s6) + " ms");
}
}
- Используется с java.version = 1.8.0_101 ( Oracle )
- x64 ОС / процессор
Результат вывода:
warming up a little...
method 1 = 1103 ms
method 2 = 872 ms
method 3 = 440 ms
method 3_1 = 418 ms
method 4 = 413 ms
method 4_1 = 376 ms
method 5 = 439 ms
method 5_1 = 384 ms
method 6 = 646 ms
В моем понимании, лучший подход из образца я тестировал использовал Files.readAllLines
, s.split(" ")
и Integer.parseInt
. Эти три комбинации снова показали себя наиболее быстрыми из образца, который я создал и протестировал с По крайней мере, возможно, вы бы поменяли на, Integer.parseInt
чтобы немного помочь.
Обратите внимание, что я использовал источники, чтобы помочь получить некоторые востребованные подходы и применил их к этой проблеме / примеру Например, этот пост в блоге , этот учебник и этот потрясающий чувак @ Питер-Лори . Кроме того, всегда могут быть сделаны дальнейшие улучшения !
Также файл test.txt:
my_name 15 00 29 101 1234
cool_id 11 00 01 10 010101
longer_id_name 1234
dynamic_er 1 2 3 4 5 6 7 8 9 10 11 12 123 1456 15689 555555555
(примечание: производительность может сильно различаться в зависимости от размера файла!)
Автор: Nick Bell Размещён: 25.10.2016 01:46Вопросы из категории :
- java В чем разница между int и Integer в Java и C #?
- java Как я могу определить IP моего маршрутизатора / шлюза в Java?
- java Каков наилучший способ проверки XML-файла по сравнению с XSD-файлом?
- java Как округлить результат целочисленного деления?
- java Преобразование списка <Integer> в список <String>
- java Почему я не могу объявить статические методы в интерфейсе?
- nio когда я использую nio, serverSocket.accept () выбрасывает IllegalBlockingModeException
- nio Получает байтовый массив из ByteBuffer в Java
- nio Java NIO: Что такое IOException: Сломанная труба означает?
- nio Java: преобразование строки в и из ByteBuffer и связанных с ней проблем
- nio Рекурсивно перечислять файлы в Java
- nio Поток Java для модели соединения против NIO
- java-io Преобразование прозрачного GIF / PNG в JPEG с использованием Java
- java-io Как вывести список файлов внутри файла JAR?
- java-io java.io.WriteAbortedException: запись прервана; java.io.NotSerializableException
- java-io как сделать File.listFiles в алфавитном порядке?
- java-io Удалить файлы с той же строкой префикса, используя Java
- java-io Как получить только имя родительского каталога для определенного файла