Показать полную графическую версию : [решено] Чтение из текстового файла строковых данных в двумерный массив java8
blackeangel
23-05-2017, 15:05
Собственно как это сделать?
Scanner использовать или reader или что?
Использовать List<List<Double>> matr = new LinkedList<>(); для подсчёта строк в файле?
Сильно не пинайте, но только начинаю изучать.
Выручайте, ребята.
Как вариант считать в одномерный, а потом переделать в двумерный массив с использованием регулярки
То есть результатом должен быть двумерный массив чаров? Ну тогда можно считывать построчно и каждую строку разбирать на символы. Считывать построчно можно, например, вот так (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
Но тут какая то беда с регуляркой »
Разумеется. Не стоит же квантификатор для первой группы, поэтому она соответствует одному любому символу. Я имею в виду "^(.)\\s(\\d+)\\s(\\d+)\\s(\\d+)$" Нужно заменить на (.+?) и тогда должно сооветствовать строкам в файле.
blackeangel
24-05-2017, 22:23
Но тут какая то беда с регуляркой »
Разумеется. Не стоит же квантификатор для первой группы, поэтому она соответствует одному любому символу. Я имею в виду "^(.)\\s(\\d+)\\s(\\d+)\\s(\\d+)$" Нужно заменить на (.+?) и тогда должно сооветствовать строкам в файле.
Увы, фокус не удался. Ещё есть догадки?
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
на отдельные операции и смотреть результат каждой. »
это как сделать?
Ну а если так?
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
?
Тоже с пробелами если попадуться?
Просто в файле встречаются и такие строки тоже.
Похоже, 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, почему не годится?
И такой метод не разбивает - все в одну строку пишет.
Потому что в методе 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 массива:в один читаем файл, во второй этот массив раскладывается по столбцам при помощи регулярки?
Вот файл… »
Ура! К шашнадцатому сообщению Вы таки об ентом вспомнили.
надо использовать 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
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.
Available in ZeroNet 1osznRoVratMCN3bFoFpR2pSV5c9z6sTC