Espressioni regolari in Java

Scripta14

Nuovo Utente
95
8
Avrei bisogno alcuni chiarimenti sull'utilizzo delle espressioni regolari, tramite il metodo split in java.
Ho un file di prova con due campi, entrambi delimitati dalle virgolette.
Vorrei estrarre da ogni riga i due campi, ma non riesco a gestire correttamente l'espressione regolare.
Riporto il frammento di codice:

try(BufferedReader in=new BufferedReader(new FileReader("Prova.txt")))
{
in.lines().map(l ->l.split("\"([^\"]*)\"|\\s*"))
.forEach(item ->{
try{
p.add(new Prova(item[0],Integer.parseInt(item[1])));
}
catch (PatternSyntaxException e){
System.err.println("Espresssione regolare non corretta");}
catch(ArrayIndexOutOfBoundsException e){
System.err.println("elemento mancante");
}
});
}

Per favore, mi potreste dire come gestire questa casistica ed eventualmente come poter gestire il metodo split qualora dovessi modificare o aggiungere dei delimitatori ai campi?

Ringrazio anticipatamente.
 

VykarR

Nuovo Utente
28
8
CPU
i7-7700 3.6 GHz
Dissipatore
Corsair Hydro H115i All-in-One Liquid CPU Cooler
Scheda Madre
MSI H270 Gaming M3
HDD
Samsung 850 EVO 500Gb + 1Tb HDD
RAM
Corsair Vengeance LPX 2x8Gb 3000Mhz
GPU
ASUS ROG-STRIX-GTX1080TI
Monitor
Samsung U28E590D 4K 28"
PSU
EVGA SuperNOVA 750W
OS
Windows 10
Ciao, se puoi modificare come sono scritti i campi nel file io ti consiglierei di scriverli in questo modo (se proprio vuoi utilizzare le virgolette).
Codice:
test1"1
test2"2

Cosi' da poter utilizzare questa espressione regolare: in.lines().map(l ->l.split("\""))

Quindi, risistemando anche un po' il tuo codice, verrebbe fuori una cosa simile:

Codice:
try(BufferedReader in=new BufferedReader(new FileReader("C:\\Prova.txt")))
        {
            in.lines().map(l ->l.split("\""))
            .forEach(item ->{
            p.add(new Prova(item[0],Integer.parseInt(item[1])));
           
        });
        }catch (PatternSyntaxException e){
        System.err.println("Espresssione regolare non corretta");}
        catch(ArrayIndexOutOfBoundsException e){
        System.err.println("elemento mancante");
        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
            System.err.println("File mancante");
        } catch (IOException e1) {
            e1.printStackTrace();
            System.err.println("Errore durante la lettura");
        }

Ho eliminato il secondo try utilizzato, va benissimo utilizzarne solo uno in questo caso. Per quanto riguarda gli ultimi due catch io li ho messi per far compilare il codice ma se il metodo in cui e' presente questo blocco che mi hai mostrato ha la clausola throws IOException non ti servono e puoi gestire direttamente l'eccezione dal chiamante.

Se ti serve qualsiasi tipo di spiegazione chiedi pure liberamente.

Nel caso non puoi modificare il file potresti mostrarmi precisamente come e' scritto?

Grazie.
 
Ultima modifica:

Scripta14

Nuovo Utente
95
8
Ciao, se puoi modificare come sono scritti i campi nel file io ti consiglierei di scriverli in questo modo (se proprio vuoi utilizzare le virgolette).
Codice:
test1"1
test2"2

Cosi' da poter utilizzare questa espressione regolare: in.lines().map(l ->l.split("\""))

Quindi, risistemando anche un po' il tuo codice, verrebbe fuori una cosa simile:

Codice:
try(BufferedReader in=new BufferedReader(new FileReader("C:\\Prova.txt")))
{
in.lines().map(l ->l.split("\""))
.forEach(item ->{
p.add(new Prova(item[0],Integer.parseInt(item[1])));

});
}catch (PatternSyntaxException e){
System.err.println("Espresssione regolare non corretta");}
catch(ArrayIndexOutOfBoundsException e){
System.err.println("elemento mancante");
} catch (FileNotFoundException e1) {
e1.printStackTrace();
System.err.println("File mancante");
} catch (IOException e1) {
e1.printStackTrace();
System.err.println("Errore durante la lettura");
}

Ho eliminato il secondo try utilizzato, va benissimo utilizzarne solo uno in questo caso. Per quanto riguarda gli ultimi due catch io li ho messi per far compilare il codice ma se il metodo in cui e' presente questo blocco che mi hai mostrato ha la clausola throws IOException non ti servono e puoi gestire direttamente l'eccezione dal chiamante.

Se ti serve qualsiasi tipo di spiegazione chiedi pure liberamente.

Nel caso non puoi modificare il file potresti mostrarmi precisamente come e' scritto?

Grazie.
Grazie per la risposta.
Il file ha questa struttura:
"testo1" "1"
"testo2" "2"
E così via...


Inviato da WAS-LX1A tramite App ufficiale di Tom\'s Hardware Italia Forum
 

VykarR

Nuovo Utente
28
8
CPU
i7-7700 3.6 GHz
Dissipatore
Corsair Hydro H115i All-in-One Liquid CPU Cooler
Scheda Madre
MSI H270 Gaming M3
HDD
Samsung 850 EVO 500Gb + 1Tb HDD
RAM
Corsair Vengeance LPX 2x8Gb 3000Mhz
GPU
ASUS ROG-STRIX-GTX1080TI
Monitor
Samsung U28E590D 4K 28"
PSU
EVGA SuperNOVA 750W
OS
Windows 10
Dopo vari tentativi penso di aver trovato una soluzione che fa al caso tuo.

Codice:
in.lines().map(l ->l.replace("\"", "").split(" ")).forEach(item ->{
                p.add(new Prova(item[0],Integer.parseInt(item[1])));
                });

In questo modo il codice effettua prima una rimozione di tutte le virgolette tramite il metodo replace che ricerca in questo caso tutte le virgolette e le sostituisce con "" cioe' nulla. Quindi a questo punto la riga sara' questa: testo1 1. Quindi ci basta utilizzare il metodo split con parametro " " (spazio) cosi' che si dividano perfettamente senza dover ricorrere a regex troppo lunghi o difficili da capire. L'importante e' che non ci siano spazi all'inizio o alla fine delle righe altrimenti in alcuni casi potrebbe andarti in errore.

Se dovessi trovare ancora problemi fammi sapere.
 
  • Mi piace
Reazioni: Scripta14

Scripta14

Nuovo Utente
95
8
Grazie, per la brillante soluzione. Vorrei chiederti un'altra cosa. Se volessi modificare il file di testo nel seguente modo:
"testo1", "1"
"testo2", "2"
e così via, come potrei riscrivere il codice? Riusciresti a darmi qualche altra brillante idea\soluzione?

Grazie
 

VykarR

Nuovo Utente
28
8
CPU
i7-7700 3.6 GHz
Dissipatore
Corsair Hydro H115i All-in-One Liquid CPU Cooler
Scheda Madre
MSI H270 Gaming M3
HDD
Samsung 850 EVO 500Gb + 1Tb HDD
RAM
Corsair Vengeance LPX 2x8Gb 3000Mhz
GPU
ASUS ROG-STRIX-GTX1080TI
Monitor
Samsung U28E590D 4K 28"
PSU
EVGA SuperNOVA 750W
OS
Windows 10
Molto semplicemente utilizzando sempre la stessa logica della precedente soluzione invece di inserire " "(spazio) come parametro del metodo split inseriamo ","(virgola) e il codice avra' lo stesso funzionamento.

Inserendo la modifica il codice sara' cosi:
Codice:
in.lines().map(l ->l.replace("\"", "").split(",")).forEach(item ->{
                p.add(new Prova(item[0],Integer.parseInt(item[1])));
                });

Il parametro utilizzabile per il metodo split e' dinamico, cioe' possiamo utilizzarlo come piu' ci e' comodo al momento e per semplificarlo ti conviene sempre avere solo un separatore per ogni elemento (Nel caso di prima era lo spazio, adesso la virgola).
 
  • Mi piace
Reazioni: Scripta14

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!