Leggere e scrivere file di properties in Java
Lo scenario è questo: vogliamo impostare i parametri di connessione al db non nel codice direttamente, ma usando un file memorizzato nella home dell'utente.
All'inizio pensavo di usare XML, ma poi mi hanno consigliato un file di properties.
Questo fila ha una struttura molto semplice di tipo chiave=valore.
Ecco il mio esempio:
#Thu Mar 31 13:17:09 CEST 2011
user=myuser
password=mypass
host=myhost
database=mydb
Prima di tutto create un file; per l'esempio mettetelo nella home directory e chiamatelo config.properties
Adesso lo create a mano, ma dovreste assicurarvi che venga creato automaticamente se non c'è.
Vi posto la classe che crea e legge il file di properties:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Properties;
public class ConfigurationProperties {
private static String fileProperties = "config.properties";
public static synchronized ArrayList getProperties() throws IOException {
ArrayList list = new ArrayList();
String result = "";
Object obj = null;
Properties props = new Properties();
props.load(new FileInputStream(System.getProperty("user.home") + "/" + fileProperties));
Enumeration e = props.keys();
while (e.hasMoreElements()) {
obj = e.nextElement();
result = props.getProperty(obj.toString());
list.add(result);
}
return list;
}
public static synchronized void setProperties(String key[], String value[]) throws IOException {
Properties properties = new Properties();
properties.load(new FileInputStream(System.getProperty("user.home") + "/" + fileProperties));
properties.setProperty(key[0], value[0]);
properties.setProperty(key[1], value[1]);
properties.setProperty(key[2], value[2]);
properties.setProperty(key[3], value[3]);
properties.store(new FileOutputStream(System.getProperty("user.home") + "/" + fileProperties, false), null);
}
}
La classe preposta al lavoro è Properties, che rappresenta un set persistente di proprietà.
Questa classe ha due metodi: uno per leggere e l'altro per settare.
Viediamo prima setProperties.
Questo metodo richiede due parametri (due array di String), che saranno i valori scritti nel file (dopo vi farò vedere come ho fatto io a passarglieli).
L'oggetto prop prima cerca di caricare il file col metodo load.
Se lo trova, scrive le varie proprietà con setProperty passando i valori dei due array.
Questo metodo infatti richiede due String come parametri e noi gli diamo i valori degli array; avreste potuto anche usare qualche ciclo senza scriverli a mano.
Infine usa il metodo store per scrivere i valori nel file caricato prima.
Per inviare i valori io ho usato un JFrame con tre JTextField e un JPasswordField.
Vi posto l'evento impostato sul bottone:
private void btnSaveActionPerformed(java.awt.event.ActionEvent evt) {
try {
char[] pwd = textPass.getPassword();
String sPwd = new String(pwd);
String[] key = {"host", "database", "user", "password"};
String[] val = {textHost.getText(), textDb.getText(), textUser.getText(), sPwd};
ConfigurationProperties.setProperties(key, val);
} catch (FileNotFoundException ex) {
JOptionPane.showMessageDialog(null, ex.getMessage());
} catch (IOException ex) {
JOptionPane.showMessageDialog(null, ex.getMessage());
}
}
Il metodo getPassword restituisce un array di char; quindi in questa riga faccio un cast:
String sPwd = new String(pwd);
Le altre stringhe le prendo dalle textfield.
Come vedete creo due array di stringhe: il primo sono le chiavi e il secondo i valori.
Richiamo il metodo passando i due array e il gioco è fatto!
La lettura è leggermente più elaborata.
Il metodo getProperties ritorna un ArrayList, che verrà letto dalla classe che effettua la connessione.
Anche qui l'oggetto Properies carica il file con load.
Le chiavi vengono lette da un oggetto Enumeration tramite il metodo keys(), che ritorna appunto un enumerato di chiavi in una hashtable.
Enumeration è una interfaccia, e un oggetto che la implementa genera una serie di elementi; in questo caso vengono letti nel ciclo while attraverso hasMoreElements() e, attraverso altre due operazioni, aggiunti all'ArrayList.
Può sembrare un pò ostico, ma se conoscete ArrayList apite il perchè di obj e result.
Detto ciò dobbiamo passare i valori ai parametri di connessione:
public class DBManager {
private static DBManager instance = null;
private String HOST = "";
private String DB = "";
private String USER = "";
private String PWD = "";
private static Connection conn = null;
private DBManager() {
}
public static DBManager getInstance() {
return (instance == null) ? (instance = new DBManager()) : instance;
}
public Connection getConnection() throws ClassNotFoundException, SQLException, IOException {
ArrayList list = ConfigurationProperties.getProperties();
String[] keys = (String[]) list.toArray(new String[list.size()]);
HOST = keys[2];
DB = keys[3];
PWD = keys[1];
USER = keys[0];
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://" + HOST + ":3306/" + DB + "?user=" + USER + "&password=" + PWD);
return conn;
}
}
La classe usa Singleton; guardate qua per capire meglio (non è obbligatorio ovviamente usare Singleton).
Comunque i 4 campi che ci servono sono inizializzati vuoti, e vengono riempiti in getConnection().
Come vedete i valori nell'array non sono nell'ordine di come li ho salvati; non chiedetemi il perchè.
Creiamo un oggetto ArrayList, facciamo il cast a String[] e valoriziamo i campi con i singoli valori.
Enjoy!
java properties enumeration arraylist string
Commentami!