Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   [решено] Чтение из текстового файла строковых данных в двумерный массив java8 (http://forum.oszone.net/showthread.php?t=327001)

blackeangel 23-05-2017 15:05 2738980

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

shisik 24-05-2017 16:50 2739278

То есть результатом должен быть двумерный массив чаров? Ну тогда можно считывать построчно и каждую строку разбирать на символы. Считывать построчно можно, например, вот так.

blackeangel 24-05-2017 21:03 2739339

Цитата:

Цитата shisik (Сообщение 2739278)
То есть результатом должен быть двумерный массив чаров? Ну тогда можно считывать построчно и каждую строку разбирать на символы. Считывать построчно можно, например, вот так.

Код:

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 2739350

Цитата:

Цитата blackeangel
Но тут какая то беда с регуляркой »

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

blackeangel 24-05-2017 22:23 2739359

Цитата:

Цитата shisik (Сообщение 2739350)
Цитата:

Цитата blackeangel
Но тут какая то беда с регуляркой »

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

Увы, фокус не удался. Ещё есть догадки?

shisik 24-05-2017 22:26 2739361

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 2739369

shisik, на бейсике было так
Код:

"^(.+) (\d+) (\d+) (\d+)(?:| (.+))$"
и все прекрасно работало. На java что-то не катит.

blackeangel 24-05-2017 23:09 2739375

Цитата:

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

это как сделать?

shisik 24-05-2017 23:15 2739376

Ну а если так?

Код:

split("\\s")
Так должно работать с пробелами в именах файлов:

Код:

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

blackeangel 25-05-2017 05:57 2739408

shisik,
Код:

split("\\s") = split(" ")
Что не есть хорошо.
А вот второй вариант попробую.

blackeangel 25-05-2017 11:59 2739483

Цитата:

Цитата shisik (Сообщение 2739376)
Так должно работать с пробелами в именах файлов:

Код:

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

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

blackeangel 25-05-2017 12:44 2739493

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

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 2739538

Похоже, 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 2739541

shisik, почему не годится?

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

shisik 25-05-2017 15:45 2739562

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

Код:

(?=\\d+(?:\\s\\d+)?(?:\\s\\d+)?$)
до конца строки не должно быть ничего кроме максимум трёх чисел, разделённых пробелами. К слову, примерно то же самое можно написать проще, но всё равно не спасает:

Код:

\\s(?![^\\d\\s]+$)
Можно пытаться дальше развивать этот шаблон, но в конечном итоге в имени файла может встретиться числа, окруженное пробелами, например File 123 name.txt - и всё, в любом случае это число будет выделено в отдельный элемент массива, а не будет частью имени файла, как должно быть. Так что этот путь тупиковый, в смысле использование split.

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

blackeangel 25-05-2017 15:57 2739565

Вот файл в котором есть варианты разновидностей.

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

blackeangel 25-05-2017 16:00 2739568

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

Iska 25-05-2017 16:40 2739580

Цитата:

Цитата blackeangel
Вот файл… »

Ура! К шашнадцатому сообщению Вы таки об ентом вспомнили.

shisik 25-05-2017 17:08 2739593

Цитата:

Цитата blackeangel
надо использовать 2 массива:в один читаем файл, во второй этот массив раскладывается по столбцам при помощи регулярки? »

Почти. Файл читается в стрим 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);

Цитата:

Цитата blackeangel
В массиве надо получить следующее:
Столбец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 2739602

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

shisik 25-05-2017 18:11 2739605

blackeangel, просто добавьте result.add("") после цикла.

blackeangel 25-05-2017 18:42 2739617

shisik, вообще волшебно) Спасибо огромное)

Iska 25-05-2017 18:57 2739621

Цитата:

Цитата blackeangel
Iska, рад вас видеть и в этой теме »

Не, не… Я тут токмо комментировать могу — не мой профиль.

blackeangel 25-05-2017 19:12 2739630

Цитата:

Цитата Iska (Сообщение 2739621)
Цитата:

Цитата blackeangel
Iska, рад вас видеть и в этой теме »

Не, не… Я тут токмо комментировать могу — не мой профиль.


Ну почему же, советы давать ещё можете - вы же со мной все это же проделывали только на бейсике :)

blackeangel 05-02-2018 23:13 2796084

shisik, приветствую Тот код что вы давали исправно работал, пока не наткнулся на непонятный файл. С виду все так, но не ест его, падает. Переписал вот так вот, но это выглядит очень страшно. Помогите разбить на функцию и её вызов
Код:

BufferedReader reader = null;
            ArrayList<String> result = new ArrayList<String>();
            Pattern pattern = Pattern.compile("^(.+?)\\s(\\d+)\\s(\\d+)\\s(\\d+)(?:\\s(.+?))?$");
            try {
                reader = new BufferedReader(new FileReader(pathStatfile));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            String line;
            while ((line = reader.readLine()) != null) {
                result.add(line);
            }
            String[][] statfilemass = new String[result.toArray().length][5];
            for (int i=0;i<result.toArray().length;i++){
                Matcher matcher = pattern.matcher(result.get(i).toString());
                if (matcher.find()) {
                    for (int j = 1; j <= matcher.groupCount(); ++j) {
                        statfilemass[i][j - 1] = matcher.group(j);
                    }
                }
            }



Время: 05:00.

Время: 05:00.
© OSzone.net 2001-