Manipulando Arquivos de Propriedades
Neste artigo utilizaremos a classe java.util.Properties
para a manipulação de arquivos de propriedades. Veremos como escrever e ler nestes arquivos. Esta classe nos permite criar dois tipos de arquivos de propriedades, o .properties
e o .xml
. Ambos os arquivos, por exemplo, podem ser vistos em configurações utilizadas no HIbernate, o hibernate.properties e o hibernate.cfg.xml
.
Uma das vantagens da utilização de arquivos de propriedades é separar configurações que podem ser alteradas a qualquer tempo do código Java. Assim, não seria necessário alterar o código Java sempre que seja necessária uma alteração nas configurações.
Os arquivos de propriedades são muito utilizados em sistemas desenvolvidos em Java. Temos configurações de internacionalização, configurações de email, jdbc, logs, entre outras. Fica a cargo do desenvolvedor saber quando é necessária sua utilização.
1. Classe JdbcConnection
Vamos criar uma classe chamada JdbcConnection
, onde criaremos atributos utilizados para conexões do tipo JDBC.
public class JdbcConnection { private String user; private String pass; private String driver; private String url; private String dataBase; // gerar os métodos getters and setters }
2. Arquivo .properties
Vamos agora criar uma classe de testes para criar e ler nosso arquivo de propriedades. Um arquivo de propriedades tem o seguinte formato, chave e valor. À direita temos a chave e a esquerda temos o valor. Um exemplo pode ser visto na listagem 2.
jdbc.dataBase = myDataBase jdbc.driver = com.mysql.jdbc.Driver jdbc.pass = admin01 jdbc.url = jdbc\:mysql\://localhost\:3306/ jdbc.user = root
Vamos então criar a classe PropertiesTest
e nela iremos criar três métodos, o método main()
é claro, e mais um método para criação do arquivo e um método para leitura do arquivo.
Listagem 3. Classe PropertiesTest
import java.io.*; import java.util.Properties; public class PropertiesTest { public static void main(String[] args) { JdbcConnection jdbc = new JdbcConnection(); jdbc.setUser("root"); jdbc.setPass("admin01"); jdbc.setDriver("com.mysql.jdbc.Driver"); jdbc.setUrl("jdbc:mysql://localhost:3306/"); jdbc.setDataBase("myDataBase"); } }
Criamos uma inst ncia da classe JdbcConnection
e então criamos um objeto com as informações que farão parte do nosso arquivo.
Vamos agora criar o método que irá gerar o arquivo jdbc.properties
.
private static void criarPropriedades(JdbcConnection jdbc) { //Cria um objeto da classe java.util.Properties Properties properties = new Properties(); //setando as propriedades(key) e os seus valores(value) properties.setProperty("jdbc.user", jdbc.getUser()); properties.setProperty("jdbc.pass", jdbc.getPass()); properties.setProperty("jdbc.driver", jdbc.getDriver()); properties.setProperty("jdbc.url", jdbc.getUrl()); properties.setProperty("jdbc.dataBase", jdbc.getDataBase()); try { //Criamos um objeto FileOutputStream FileOutputStream fos = new FileOutputStream("C:\\jdbc.properties"); //grava os dados no arquivo properties.store(fos, "FILE JDBC PROPERTIES:"); //fecha o arquivo fos.close(); } catch (IOException ex) { System.out.println(ex.getMessage()); ex.printStackTrace(); } }
Criamos um objeto properties onde setamos as propriedades através do método setProperty()
. Como já explicado anteriormente, o primeiro valor é a chave ou o nome da propriedade, e o segundo valor é o valor da propriedade propriamente dita.
O objeto fos cria o fluxo para escrever no arquivo definido em seu construtor. O método store()
é quem faz a mágica da classe Properties
, nela passamos como parametro o objeto fos
e uma descrição para o arquivo. Caso não queira setar uma descrição, o parametro pode ser null
.
Após a execução deste método, teremos a seguinte saída, que pode ser visualizada na listagem 5.
#FILE JDBC PROPERTIES: #Wed Mar 30 15:48:34 BRT 2011 jdbc.url = jdbc\:mysql\://localhost\:3306/ jdbc.driver = com.mysql.jdbc.Driver jdbc.user = root jdbc.dataBase = myDataBase jdbc.pass = admin01
Agora vamos criar um método para ler as propriedades deste arquivo. Para isso, faça como na listagem 6.
private static void lerPropriedades() { Properties properties = new Properties(); try { //Setamos o arquivo que vai ser lido FileInputStream fis = new FileInputStream("C:\\jdbc.properties"); //metodo load faz a leitura atraves do objeto fis properties.load(fis); } catch (IOException e) { e.printStackTrace(); } //Captura o valor da propriedade, atraves do nome da propriedade(Key) String p1 = properties.getProperty("jdbc.user"); String p2 = properties.getProperty("jdbc.pass"); String p3 = properties.getProperty("jdbc.driver"); String p4 = properties.getProperty("jdbc.url"); String p5 = properties.getProperty("jdbc.dataBase"); System.out.println(p1 + "\n" + p2 + "\n" + p3 + "\n" + p4 + "\n" + p5); }
Se para setar as propriedades usavamos o método setProperty()
, agora para ler precisamos usar o método getProperty()
, desta vez, setamos apenas a chave referente ao valor que queremos recuperar no arquivo.
Execute o método de leitura e veja no console que terá uma saída com os valores das propriedades existentes no arquivo jdbc.properties
.
3. Arquivo .xml
Vamos agora criar o arquivo de propriedades, mas não no formato .properties
, e sim no formato .xml
. Um exemplo de arquivo de propriedades no formato XML pode ser visualizado na figura 1.
Para gerar o arquivo XML precisamos apenas trocar o método store()
pelo método storeToXML()
. E vamos passar mais um par metro que seta o encoding do XML.
Também deve ser alterado o tipo de arquivo de .properties
para .xml
, não esqueça de efetuar esta troca. Confira na listagem 7 a chamada ao método storeToXML()
.
properties.storeToXML(fos, "FILE JDBC XML:", "ISO-8859-1");
Para efetuar a leitura do arquivo XML precisamos trocar o método load()
pelo método loadFromXML()
, conforme a listagem 8.
properties.loadFromXML(fis);
Muito simples com certeza. Agora você pode decidir qual tipo de arquivo prefere utilizar nas diversas aplicações que fará.
4. Ordenando o conteúdo dos arquivos
Como você pode notar, se ainda não notou vai perceber agora, o arquivo não fica organizado. Tanto o arquivo do tipo properties quanto o do tipo XML tem suas chaves fora de ordem. Não que isso faça diferença, mas é muito melhor ter um arquivo organizado de alguma forma.
Podemos criar o arquivo em ordem alfabética, para isso vamos criar uma nova classe com um método para cada tipo de arquivo que será criado.
import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.Collections; import java.util.Enumeration; import java.util.Properties; import java.util.TreeSet; import java.util.Set; public class SortedKey { public void sortedProperties(Properties properties, File file, String comments) { Properties props = new Properties() { @Override public synchronized Enumeration<Object> keys() { return Collections.enumeration( new TreeSet<Object>(super.keySet()) ); } }; props.putAll(properties); try { props.store(new FileOutputStream(file), comments); } catch (IOException e) { e.printStackTrace(); } } public void sortedXml(Properties properties, File file, String comments, String encoding) { Properties props = new Properties() { @Override public Set<Object> keySet() { return Collections.unmodifiableSet( new TreeSet<Object>(super.keySet()) ); } }; props.putAll(properties); try { props.storeToXML(new FileOutputStream(file), comments, encoding); } catch (IOException e) { e.printStackTrace(); } } }
Como a classe java.util.Properties
herda a classe java.util.Hashtable
que não é um tipo de coleção que possui ordenação, precisamos fazer a ordenação de uma forma um pouco mais complicada, mas nem tanto assim.
Para ordenar o arquivo .properties
criamos uma classe anônima do tipo Properties
, e nesta classe criamos um método que retorna uma coleção do tipo java.util.Enumeration
, que é um interface. Esta coleção obtemos através do retorno de um método da classe java.util.Collections
, chamado enumeration()
. Neste método passamos como parametro um objeto do tipo java.util.TreeSet
, que é uma coleção ordenada por padrão.
Adicionamos nesta classe anônima, através de seu o objeto props
, o objeto properties recebido como parametro, e então, ela irá ordenar por ordem alfabética as chaves de nosso arquivo. E por fim o arquivo será salvo.
A ordenação para o arquivo .xml
funciona quase da mesma forma, pelo menos utiliza o mesmo principio, criação da classe anônima e de um método que irá devolver o objeto ordenado.
Para testar estes dois métodos, vamos fazer criar um novo método que salva nossos arquivos, veja na listagem 10.
private static void criarArquivosOrdenados(JdbcConnection jdbc) { Properties properties = new Properties(); properties.setProperty("jdbc.user", jdbc.getUser()); properties.setProperty("jdbc.pass", jdbc.getPass()); properties.setProperty("jdbc.driver", jdbc.getDriver()); properties.setProperty("jdbc.url", jdbc.getUrl()); properties.setProperty("jdbc.dataBase", jdbc.getDataBase()); new SortedKey().sortedProperties( properties, "C:\\jdbc.properties", "Arquivo de Propriedades" ); new SortedKey().sortedXml( properties, "C:\\jdbc.xml", "Arquivo XML", "ISO-8859-1" ); }
Executando este novo método teremos uma saída diferente das anteriores, veja na figura 2 a diferença entre os arquivos com e sem ordenação.
Veja que como usamos a palavra jdbc na frente, a ordenação é feita pela segunda palavra após o ponto, de forma alfabética.
Conclusão
Neste tutorial vimos como criar e ler um arquivo de propriedades através da classe java.util.Properties
, sendo ele do tipo .properties
ou .xml
. Também vimos como ordenar através das chaves o conteúdo escrito nestes arquivos.
Não deixe de ler a documentação das classes e interfaces utilizadas para entender como funcionam os métodos internos, é sempre uma boa prática.
Saiba mais
- Documentação do classe java.io.FileOutputStream
- Documentação da classe java.io.FileInputStream
- Documentação da classe java.util.Properties
- Documentação da classe java.util.Collection
- Documentação da classe java.util.Enumeration
- Documentação da classe java.util.TreeSet
- Documentação da classe java.util.Set