PDA

Показать полную графическую версию : [решено] Чтение из текстового файла строковых данных в двумерный массив java8


Страниц : [1] 2

blackeangel
23-05-2017, 15:05
Собственно как это сделать?
Scanner использовать или reader или что?
Использовать List<List<Double>> matr = new LinkedList<>(); для подсчёта строк в файле?
Сильно не пинайте, но только начинаю изучать.
Выручайте, ребята.
Как вариант считать в одномерный, а потом переделать в двумерный массив с использованием регулярки

shisik
24-05-2017, 16:50
То есть результатом должен быть двумерный массив чаров? Ну тогда можно считывать построчно и каждую строку разбирать на символы. Считывать построчно можно, например, вот так (https://www.tutorialspoint.com/java/io/bufferedreader_readline.htm).

blackeangel
24-05-2017, 21:03
То есть результатом должен быть двумерный массив чаров? Ну тогда можно считывать построчно и каждую строку разбирать на символы. Считывать построчно можно, например, вот так (https://www.tutorialspoint.com/java/io/bufferedreader_readline.htm).

try {
Path path = Paths.get(pathStatfile);
String[][] array = Files.lines(path)
.map(s -> s.split("^(.)\\s(\\d+)\\s(\\d+)\\s(\\d+)$"))
// .map(s -> s.split(" "))
.toArray(String[][]::new);
System.out.println(Arrays.toString(array));
} catch (IOException e1) {
}

Но тут какая то беда с регуляркой
А вот пример строк в файле

system/lost+found 0 0 770
system/app 0 0 755
system/app/AnalyticsCore 0 0 755
system/app/AnalyticsCore/AnalyticsCore.apk 0 0 644
system/app/AnalyticsCore/oat 0 0 755
system/app/AnalyticsCore/oat/arm64 0 0 755
system/app/AnalyticsCore/oat/arm64/AnalyticsCore.odex 0 0 644
system/app/AntHalService 0 0 755
system/app/AntHalService/AntHalService.apk 0 0 644
system/app/AntHalService/oat 0 0 755
system/app/AntHalService/oat/arm64 0 0 755
system/app/AntHalService/oat/arm64/AntHalService.odex 0 0 644

shisik
24-05-2017, 21:38
Но тут какая то беда с регуляркой »

Разумеется. Не стоит же квантификатор для первой группы, поэтому она соответствует одному любому символу. Я имею в виду "^(.)\\s(\\d+)\\s(\\d+)\\s(\\d+)$" Нужно заменить на (.+?) и тогда должно сооветствовать строкам в файле.

blackeangel
24-05-2017, 22:23
Но тут какая то беда с регуляркой »

Разумеется. Не стоит же квантификатор для первой группы, поэтому она соответствует одному любому символу. Я имею в виду "^(.)\\s(\\d+)\\s(\\d+)\\s(\\d+)$" Нужно заменить на (.+?) и тогда должно сооветствовать строкам в файле.
Увы, фокус не удался. Ещё есть догадки?

shisik
24-05-2017, 22:26
blackeangel, предлагаю разбить цепочку вызовов

String[][] array = Files.lines(path)
.map(s -> s.split("^(.)\\s(\\d+)\\s(\\d+)\\s(\\d+)$"))
.toArray(String[][]::new);

на отдельные операции и смотреть результат каждой.

blackeangel
24-05-2017, 22:41
shisik, на бейсике было так
"^(.+) (\d+) (\d+) (\d+)(?:| (.+))$"

и все прекрасно работало. На java что-то не катит.

blackeangel
24-05-2017, 23:09
на отдельные операции и смотреть результат каждой. »
это как сделать?

shisik
24-05-2017, 23:15
Ну а если так?

split("\\s")

Так должно работать с пробелами в именах файлов:

split("\\s(?=\\d+(?:\\s\\d+)?(?:\\s\\d+)?$)")

blackeangel
25-05-2017, 05:57
shisik,

split("\\s") = split(" ")

Что не есть хорошо.
А вот второй вариант попробую.

blackeangel
25-05-2017, 11:59
Так должно работать с пробелами в именах файлов:

split("\\s(?=\\d+(?:\\s\\d+)?(?:\\s\\d+)?$)")

Ура! Заработало) Спасибо огромное!)

blackeangel
25-05-2017, 12:44
А как теперь доработать ту регулярку так, чтобы ещё можно было захватить и такие строки

system/app/PicoTts/lib/arm/libttscompat.so 0 0 644 /system/lib/libttscompat.so
system/app/PicoTts/lib/arm/libttspico.so 0 0 644 /system/lib/libttspico.so

?
Тоже с пробелами если попадуться?
Просто в файле встречаются и такие строки тоже.

shisik
25-05-2017, 14:50
Похоже, split для этого не годится. А что если так?

private static String [] parseLine(String line) {
ArrayList<String> result = new ArrayList<String>();
Pattern pattern = Pattern.compile("^(.+?)\\s(\\d+)\\s(\\d+)\\s(\\d+)(?:\\s(.+?))?$");
Matcher matcher = pattern.matcher(line);
while (matcher.find()) {
result.add(matcher.group());
}
return result.toArray(new String[0]);
}

//...

String[][] array = Files.lines(path)
.map(s -> parseLine(s))
.toArray(String[][]::new);

blackeangel
25-05-2017, 15:06
shisik, почему не годится?

И такой метод не разбивает - все в одну строку пишет.

shisik
25-05-2017, 15:45
Потому что в методе split регулярка задаёт шаблон разделителя, а не всей разделяемой строки. Пока в строке после имени файла ожидались лишь цифры и пробелы, можно было проделать трюк с проверкой на наличие таких символов после пробела и таким образом не считать разделителем пробелы внутри имени файла. Если после этого пробела есть символы, не удовлетворяющие условию, например, буквы. Именно это делает часть

(?=\\d+(?:\\s\\d+)?(?:\\s\\d+)?$)

до конца строки не должно быть ничего кроме максимум трёх чисел, разделённых пробелами. К слову, примерно то же самое можно написать проще, но всё равно не спасает:

\\s(?![^\\d\\s]+$)

Можно пытаться дальше развивать этот шаблон, но в конечном итоге в имени файла может встретиться числа, окруженное пробелами, например File 123 name.txt - и всё, в любом случае это число будет выделено в отдельный элемент массива, а не будет частью имени файла, как должно быть. Так что этот путь тупиковый, в смысле использование split.

А вот написать регулярку, соответствующую всей строке целиком - это возможно и совсем несложно. Что и сделал. Но только тогда split уже не годится.

blackeangel
25-05-2017, 15:57
Вот файл в котором есть варианты разновидностей.

В массиве надо получить следующее:
Столбец0: путь к файлу и имя файла
Столбец1-столбец3: права(0 0 0764)
Столбец4: пустой и заполненный в зависимости от наличия заполнителя
Столбец5:пустой

blackeangel
25-05-2017, 16:00
shisik, то есть надо использовать 2 массива:в один читаем файл, во второй этот массив раскладывается по столбцам при помощи регулярки?

Iska
25-05-2017, 16:40
Вот файл… »
Ура! К шашнадцатому сообщению Вы таки об ентом вспомнили.

shisik
25-05-2017, 17:08
надо использовать 2 массива:в один читаем файл, во второй этот массив раскладывается по столбцам при помощи регулярки? »

Почти. Файл читается в стрим (https://habrahabr.ru/company/luxoft/blog/270383/) Stream<String>. Метод map применяет некоторую функцию к каждому элементу стрима (строке из файла), результатом которой является массив строк, то есть на выходе имеем Stream<String[]>. Затем toArray преобразовывает стрим в массив с теми эже элементами, что были в стриме, то есть в String[][]. Когда я говорил разбить цепочку вызовов на отдельные части, я имел в виду что-то типа такого:

Stream<String> str_stream = Files.lines(path);
Stream<String[]> arr_stream = str_stream.map(s -> parseLine(s));
String[][] array = arr_stream.toArray(String[][]::new);

В массиве надо получить следующее:
Столбец0: путь к файлу и имя файла
Столбец1-столбец3: права(0 0 0764)
Столбец4: пустой и заполненный в зависимости от наличия заполнителя
Столбец4:пустой »

Не понял: два раза «столбец 4»? Наверно, последняя строка не нужна. Просто

0: имя файла
1 - 3: права
4 - или всё, что после прав, или ничего.

Так? В общем, вот:

private static String [] parseLine(String line) {
ArrayList<String> result = new ArrayList<String>();
Pattern pattern = Pattern.compile("^(.+?)\\s(\\d+)\\s(\\d+)\\s(\\d+)(?:\\s(.+?))?$");
Matcher matcher = pattern.matcher(line);
if (matcher.find()) {
for (int i = 1; i <= matcher.groupCount(); ++i) {
result.add(matcher.group(i));
}
}
return result.toArray(new String[0]);
}

blackeangel
25-05-2017, 17:52
shisik, описАлся, простите. 5й пустой. Ну да ладно, переберу массив в новый на 1 столбец больше.
Iska, рад вас видеть и в этой теме ;)




© OSzone.net 2001-2012