IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze: Načítanie hodnôt zo súboru z viacerých stĺpcov, problém s medzerami

V předchozím kvízu, Online test znalostí Java, jsme si ověřili nabyté zkušenosti z kurzu.

Aktivity
Avatar
Neaktivní uživatel:9.4.2020 22:45

Ahojte,

mám jeden problém a bola by som rada keby ste mi niekto poradili.

Mám takýto program:

Mám načítať hodnoty zo súboru, ktorý vyzerá takto:
1 2 3
2 3 4
3 4 5
tých riadkov je tam oveľa viacej. Mojou úlohou je najskôr zistíť koľko riadkov súbor má, následne na to vytvoriť 2-rozmerné pole a nahrať tam tieto hodnoty:
Pole[i][0] = 1
Pole[i][1] = 2
Pole[i][2] = 3
a pole sa má vypísať. Problém je v tom, že neviem ako mám načítať tie hodnoty do poľa. Pretože všetky riadky majú na začiatku 4 medzery a ešte medzi číslami je 1 medzera.

Zkusil jsem: Skúšala som to so split(), skúšala vymazať medzery aj cez replaceAll, ale nič mi to nepomohlo. Taktiež skúsila zmeniť pole z int na String.

To je môj kód:

class Uloha {

    private final File file;
    private int pocetHran;

    public Uloha() throws FileNotFoundException {
        this.file = new File("C:\\Users\\*****\\Desktop\\FRI\\2. semester\\ATG\\pr1.hrn");

        this.pocetHran = 0;
    }

    void zistiHrany() throws FileNotFoundException {
        Scanner scanner = new Scanner(this.file);
        while (scanner.hasNextLine()) {
            System.out.println(scanner.nextLine());
            this.pocetHran++;
        }
        System.out.println("Pocet hran: " + this.pocetHran);
       scanner.close();
    }

    void aa() throws FileNotFoundException {
        Scanner novyScanner = new Scanner(this.file);
        int[][] H = new int[this.pocetHran][3];
        for (int i = 0; (i < this.pocetHran) && novyScanner.hasNextLine(); i++) {
            for (int j = 0; j < 3; j++) {
                H[i][j] = novyScanner.nextInt();
            }
        }

        for (int i = 0; i < this.pocetHran; i++) {
            for (int j = 0; j < 3; j++) {
                System.out.print(H[i][j]);
            }
            System.out.println();
        }
        novyScanner.close();
    }
}

Chci docílit: Ako som už napísala, snažím sa načítať tie hodnoty do poľa.

Ďakujem za akúkoľvek radu.

Odpovědět
9.4.2020 22:45
Neaktivní uživatelský účet
Avatar
Odpovídá na Neaktivní uživatel
Matúš Olejník:10.4.2020 3:53

Ahoj, nedá sa mi zaspať tak tu som niečo napísal :D Na nejasnosti sa kľudne pýtaj v komentoch nemám síl to nejako viacej popisovať teraz :D Snáď som išiel podľa zadania :)

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

class Main {

    private static final String FILE_NAME = "file.txt";
    private static final String COLUMNS_DELIMETER = " ";
    private static final String LINES_DELIMETER = "\n";

    public static void main(String[] args) {
        Main main = new Main();
        String[][] parsedFile;
        try {
            int linesCount = main.getLinesCountOfFile(FILE_NAME);
            parsedFile = main.parseFileInto2DArray(FILE_NAME, linesCount);
            main.print2DArray(parsedFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void print2DArray(String[][] array){
        for(int i = 0; i < array.length; i++){
            for(int j = 0; j < array[i].length; j++){
                System.out.print(array[i][j]);
                System.out.print(COLUMNS_DELIMETER);
            }
            System.out.print(LINES_DELIMETER);
        }
    }

    public String[][] parseFileInto2DArray(String fileName, int linesCount) throws IOException {
        BufferedReader reader = new BufferedReader(new FileReader(fileName));

        String[][] result = new String[linesCount][];

        int lineIndex = 0;
        String line = reader.readLine();
        while (line != null) {
            result[lineIndex++] = line.trim().split(" ");
            line = reader.readLine();
        }

        reader.close();

        return result;
    }

    public int getLinesCountOfFile(String fileName) throws IOException {
        BufferedReader reader = new BufferedReader(new FileReader(fileName));
        int linesCount = 0;
        while (reader.readLine() != null) {
            linesCount++;
        }
        reader.close();

        return linesCount;
    }
}
Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
Nahoru Odpovědět
10.4.2020 3:53
/* I am not sure why this works but it fixes the problem */
Avatar
Ondřej Němec
Tvůrce
Avatar
Ondřej Němec:10.4.2020 21:58

Koukal jsem na to, ten tvůj kód funguje podle zadání, co dala itecko
Podle mě jsou tu tři oblasti, ve kterých by se dal vylepšit - v závislosti na tom, k čemu ten kod bude:

  • algoritmus funguje pro mezery před i za číselnou sekvencí, ale více mezer mezi čísly je problém
  • nevím, co se má s výsledným polem dělat dál, pokud pouze vypsat, je to OK, pokud s ním ještě budou pracovat - např. v další úloze - nebylo by lepší vracet pole int/Integer?
  • Není úplně optimální to dvojí procházení souboru, itecko píše, že v něm je mnohem více dat. Přiznávám ale, že pokud MUSÍM použít pole a ne list, tak mě lepší řešení nenapadá
Nahoru Odpovědět
10.4.2020 21:58
Život by byl mnohem jednodušší, kdybychom k němu měli zdrojový kód.
Avatar
Odpovídá na Ondřej Němec
Matúš Olejník:11.4.2020 0:02

Súhlasím, že by sa dal vylepšiť a preto som napísal, že nech keď tak napíše komentár nech to doladíme :)
Preto som aj pre jednoduchosť vrátil pole Stringov.

Ohľadom medzier, napísala priamo

všetky riadky majú na začiatku 4 medzery a ešte medzi číslami je 1 medzera

A jasné, že keby môže použiť List tak by to bolo úplne o inom :D Navyše napísala

najskôr zistíť koľko riadkov súbor má, následne na to vytvoriť 2-rozmerné pole

Nahoru Odpovědět
11.4.2020 0:02
/* I am not sure why this works but it fixes the problem */
Avatar
Neaktivní uživatel:11.4.2020 17:52

Ahojte chalani,

ďakujem za rýchlu odpoveď a pomoc. :) Ale mám ešte jednu otázku, skopčila som tvoj kód do NetBeansu a vyhadzuje mi stále error - java.lang.NoClas­sDefFoundError. Mohli by ste mi aj s týmto pomôcť?

Ďakujem. :D

Nahoru Odpovědět
11.4.2020 17:52
Neaktivní uživatelský účet
Avatar
Odpovídá na Neaktivní uživatel
Matúš Olejník:11.4.2020 18:13

Pošli screen ako si to tam skopčila aj so štruktúrou projektu a aj celú chybu sem pošli :)

Nahoru Odpovědět
11.4.2020 18:13
/* I am not sure why this works but it fixes the problem */
Avatar
Nahoru Odpovědět
12.4.2020 20:12
Neaktivní uživatelský účet
Avatar
Odpovídá na Neaktivní uživatel
Matúš Olejník:12.4.2020 20:42

Súbor v do ktorého si to skopírovala má názov ATGPriklad1.java preto tak premenuj aj triedu Main čo si tam skopírovala alebo naopak.

Nahoru Odpovědět
12.4.2020 20:42
/* I am not sure why this works but it fixes the problem */
Avatar
Neaktivní uživatel:12.4.2020 22:16

Ďakujeem moc, ide mi to. :)

Ale ešte mám jednu otázku, dá sa to 2D pole prerobiť zo String na int?

Nahoru Odpovědět
12.4.2020 22:16
Neaktivní uživatelský účet
Avatar
Odpovídá na Neaktivní uživatel
Matúš Olejník:12.4.2020 23:01

Prečo by sa nedalo, ale to si si mohla aj sama skúsiť :D

public int [][] parseFileInto2DArray(String fileName, int linesCount) throws IOException {
    BufferedReader reader = new BufferedReader(new FileReader(fileName));

    int[][] result = new int[linesCount][];

    int lineIndex = 0;
    String[] stringNumbers;
    String line = reader.readLine();
    while (line != null) {
        stringNumbers = line.trim().split(" ");
        result[lineIndex++] = stringArrayIntoIntArray(stringNumbers);
        //alebo
        //result[lineIndex++] = Arrays.stream(stringNumbers).mapToInt(Integer::parseInt).toArray();
        line = reader.readLine();
    }

    reader.close();

    return result;
}

public int[] stringArrayIntoIntArray(String[] stringArray){
    int[] intArray = new int[stringArray.length];
    for(int i = 0; i < stringArray.length; i++){
        intArray[i] = Integer.parseInt(stringArray[i]);
    }
    return intArray;
}
Nahoru Odpovědět
12.4.2020 23:01
/* I am not sure why this works but it fixes the problem */
Avatar
Ondřej Němec
Tvůrce
Avatar
Odpovídá na Matúš Olejník
Ondřej Němec:13.4.2020 14:00

Ale ešte mám jednu otázku, dá sa to 2D pole prerobiť zo String na int?

Neříkal jsem to? :-)
ještě bych navrhoval využít možnosti javy a nepatlat se s managentem streamů a využít try-with-resources
možná by se i hodilo dát Integer.parseInt do try catch pro případ vadného souboru
Výsledný kod:

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class Main {

    private static final String FILE_NAME = "file.txt";
    private static final String COLUMNS_DELIMETER = " ";
    private static final String LINES_DELIMETER = "\n";

    public static void main(String[] args) {
        Main main = new Main();
        int[][] parsedFile;
        try {
            int linesCount = main.getLinesCountOfFile(FILE_NAME);
            parsedFile = main.parseFileInto2DArray(FILE_NAME, linesCount);
            main.print2DArray(parsedFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void print2DArray(int[][] array){
        for(int i = 0; i < array.length; i++){
            for(int j = 0; j < array[i].length; j++){
                System.out.print(array[i][j]);
                System.out.print(COLUMNS_DELIMETER);
            }
            System.out.print(LINES_DELIMETER);
        }
    }

    public int[][] parseFileInto2DArray(String fileName, int linesCount) throws IOException {
        // vyuziti try-with-resources - samo zavre stream
        try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) {
                int[][] result = new int[linesCount][];

            int lineIndex = 0;
            String[] stringNumbers;
            String line = reader.readLine();
            while (line != null) {
                stringNumbers = line.trim().split(" ");
                result[lineIndex++] = stringArrayIntoIntArray(stringNumbers);
                //alebo
                //result[lineIndex++] = Arrays.stream(stringNumbers).mapToInt(Integer::parseInt).toArray();
                line = reader.readLine();
            }
            return result;
        }
    }

    public int[] stringArrayIntoIntArray(String[] stringArray){
        int[] intArray = new int[stringArray.length];
        for(int i = 0; i < stringArray.length; i++){
                intArray[i] = Integer.parseInt(stringArray[i]);
                /* nebo
                // pojistka pro pripad spatneho souboru
                try {
                        intArray[i] = Integer.parseInt(stringArray[i]);
                } catch (NumberFormatException e) {
                        // napr: System.err.println("This is not Integer: " + stringArray[i]);
                }
                */
        }
        return intArray;
    }

    public int getLinesCountOfFile(String fileName) throws IOException {
        // vyuziti try-with-resources - samo zavre stream
        try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) {
                int linesCount = 0;
            while (reader.readLine() != null) {
                linesCount++;
            }
            return linesCount;
        }
    }
}
Nahoru Odpovědět
13.4.2020 14:00
Život by byl mnohem jednodušší, kdybychom k němu měli zdrojový kód.
Avatar
Ondřej Němec
Tvůrce
Avatar
Odpovídá na Neaktivní uživatel
Ondřej Němec:13.4.2020 14:06

měl bych jeden dotaz, už jsme na to narazili:

je naprosto nutné použít 2D pole?

Nahoru Odpovědět
13.4.2020 14:06
Život by byl mnohem jednodušší, kdybychom k němu měli zdrojový kód.
Avatar
Odpovídá na Ondřej Němec
Neaktivní uživatel:13.4.2020 14:36

V zadaní mám vyslovene napísané použiť 2D pole, takže si myslím, že áno.

Nahoru Odpovědět
13.4.2020 14:36
Neaktivní uživatelský účet
Avatar
Odpovídá na Matúš Olejník
Neaktivní uživatel:13.4.2020 14:38

Ďakujeeem moc aj častejšie by sa ti nemuselo dať zaspať. :) A prepáč, že ťa tak otravujem.

Nahoru Odpovědět
13.4.2020 14:38
Neaktivní uživatelský účet
Avatar
Odpovídá na Neaktivní uživatel
Matúš Olejník:13.4.2020 15:03

Nemáš sa za čo ospravedlňovať :D, rád pomôžem keď viem pomôcť ;)

Nahoru Odpovědět
13.4.2020 15:03
/* I am not sure why this works but it fixes the problem */
Avatar
Neaktivní uživatel:13.4.2020 17:26

Predsa len ešte mám menší problém. :-|

Nahoru Odpovědět
13.4.2020 17:26
Neaktivní uživatelský účet
Avatar
Odpovídá na Neaktivní uživatel
Matúš Olejník:13.4.2020 17:40

Tak potom medzi číslami nemusí byť vždy len jedna medzera ako si písala či? :D Inak v tých štyroch screenoch je na riadku 71 vždy niečo iné

Nahoru Odpovědět
13.4.2020 17:40
/* I am not sure why this works but it fixes the problem */
Avatar
Odpovídá na Matúš Olejník
Neaktivní uživatel:13.4.2020 19:21

Je to možné, no nič nechajme to už tak aj tak moooc ďakujeem za pomoc :)

Nahoru Odpovědět
13.4.2020 19:21
Neaktivní uživatelský účet
Avatar
Odpovídá na Neaktivní uživatel
Matúš Olejník:13.4.2020 19:36

Nie je za čo, ale prečo to nedotiahnuť do konca? :D
tam kde sa spracováva riadok pridaj replaceAll s tým, že chceš viaceré za sebou medzery nahradiť jednou

stringNumbers = line.trim().replaceAll(" +", " ").split(" ");
Nahoru Odpovědět
13.4.2020 19:36
/* I am not sure why this works but it fixes the problem */
Avatar
Ondřej Němec
Tvůrce
Avatar
Odpovídá na Neaktivní uživatel
Ondřej Němec:13.4.2020 22:19

Nebo můžeš použít tu zakomentovanou pojistku, co jsem sdílel naposledy, cca 9 komentářů více - i když tam někdo např. místo nuly dá o (písmeno), tak to algoritmus rozchodí

Nahoru Odpovědět
13.4.2020 22:19
Život by byl mnohem jednodušší, kdybychom k němu měli zdrojový kód.
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 20 zpráv z 20.