La clase estándar de Java Properties (java.util.Properties) permite manipular archivos que almacenen de manera permanente una serie de valores emparejados cada uno de ellos a un nombre, de manera similar a los nombre de variables que almacenan valores en memoria.

Contenido del archivo properties

Un archivo de este tipo almacena la información como texto con un formato similar al siguiente:

#Ejemplo Properties
#Mon Mar 24 20:50:56 CET 2014
lastAccess=1395690656760
language=ES

Como puedes observar en el ejemplo anterior, se pueden indicar comentarios empezándolos con el carácter #, y cada una de las propiedades (en el ejemplo se usan lastAccess y language) se indican de manera similar a la asignación de valores a variables, es decir, indicando el nombre de la propiedad seguido del signo = y el valor de la propiedad.

Tambiés es posible manejar estos archivos de propiedades en formato XML. Si es así tendrá un formato similar al siguiente:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>Ejemplo Properties</comment>
<entry key="lastAccess">1395690656760</entry>
<entry key="language">ES</entry>
</properties>

Aunque estos archivos pueden ser generados directamente desde una aplicación Java, también pueden ser editados desde cualquier editor de textos sencillo, para luego leer la información que contienen desde la aplicación.

Creación del objeto Properties

Para manipular la información contenida en un archivo de propiedades, se debe instanciar un objeto de la clase Properties usando uno de sus constructores. La manera más sencilla puede ser similar a la siguiente:

Properties properties = new Properties();

Leer los valores desde un archivo

El método load de la clase Properties permite cargar en un objeto Properties los valores de las propiedades que se encuentren almacenados en un archivo.

Puedes utilizar cualquiera de los siguientes formatos:

void load(Reader reader)

void load(InputStream inStream)

Como puedes ver, puedes indicar como parámetro un objeto Reader (p.e. BufferedReader o FileReader) o bien un objeto InputStream (p.e. FileInputStream). Como ejemplo puedes hacer algo similar a uno de estos casos:

properties.load(new FileReader("nombre_archivo.properties"));
properties.load(new BufferedReader(new FileReader("nombre_archivo.properties")));
properties.load(new FileInputStream("nombre_archivo.properties"));

Como es habitual, si no indicas una ruta determinada junto con el nombre del archivo, éste se creará en la misma carpeta donde se esté ejecutando la aplicación, o en la carpeta del proyecto durante el desarrollo del mismo.

En caso de que el archivo de propiedades se encuentre dentro de uno de los paquetes de fuentes del proyecto, ten en cuenta que no se podrá modificar su contenido con la ejecución de la aplicación. Para acceder al archivo que se encuentre en uno de los paquetes de fuentes puedes utilizar una llamada a getClass().getResourceAsStream() como el siguiente ejemplo:

properties.load(getClass().getResourceAsStream("/nombre_paquete/nombre_archivo.properties"));

En este último caso puedes también puedes utilizar en lugar de getClass() directamente el nombre de la clase donde te encuentres, seguido de .class. Esto te será de utilidad sobre todo si estás en un método static. ya que ahí no podrás usar getClass().

properties.load(NombreClase.class.getResourceAsStream("/nombre_paquete/nombre_archivo.properties"));

En caso de que el archivo se encuentre en formato XML deberás usar el método loadFromXML:

void loadFromXML(InputStream in)

Obtener el valor de una propiedad

El valor asociado a cualquiera de las propiedades contenidas en un objeto Properties se puede obtener usando el método getProperty() de esa clase siguiendo uno de estos formatos:

String getProperty (String key)

String getProperty (String key, String defaultValue)

El parámetro key hace referencia al nombre que se le ha asignado a la propiedad. La diferencia entre un formato y otro radica en el resultado en caso de que no se encuentre la propiedad buscada. En el primer caso se asigna el valor null, y en el segundo se asigna el valor por defecto indicado como defaultValue.

Suponiendo que se tiene una propiedad con el nombre language, se puede obtener el valor que contiene con una sentencia como la del siguiente ejemplo, en el que se asigna el valor "ES" a la variable de tipo String language, en caso de que no se encuentre una propiedad con ese mismo nombre.

String language = properties.getProperty("language", "ES");

Aunque en el ejemplo se haya asignado el mismo nombre a la variable que almacenará el valor obtenido y al nombre de la propiedad, puedes usar nombres diferentes, aunque será habitual encontrarte con casos como este.

Cambiar el valor de una propiedad

Para modificar el valor de cualquier propiedad contenida en un objeto Properties (ojo, en el objeto, no en el archivo), debes usar el método setProperty de esa misma clase:

Object setProperty (String key, String value)

Por ejemplo, para modificar la propiedad usada en el ejemplo anterior, puede usar:

properties.setProperty("language", "FR");

El método retorna un Object con el valor que tuviera anteriormente la propiedad o null si no tenía ningún valor.

Almacenar las propiedades en un archivo

El valor contenido por las propiedades de un objeto Properties se perderán si no se almacenan en un archivo al que podrá acceder en otro momento la aplicación para hacer uso de los valores que tenían por última vez dichas propiedades. Para volcar el contenido a un archivo de tipo texto puedes usar el método store, o el método storeToXML si lo deseas en formato XML.

void store(Writer writer, String comments)

void store(OutputStream out, String comments)

void storeToXML(OutputStream os, String comment)

void storeToXML(OutputStream os, String comment, String encoding)

En el primer parámetro deberás indicar un objeto Writer (p.e. BufferedWriter, FileWriter) o bien un OutputStream (p.e. FileOutputStream). El segundo parámetro hará referencia al comentario que deseas almacenar en el archivo que aparece como puedes ver en los ejemplos de los contenidos mostrados al inicio. En el caso de los archivos de texto, se añade además de forma automática la fecha y hora de modificación del archivo. En el caso de los archivos XML, puedes indicar también el tipo de codificación deseada (p.e. "UTF-8", "ISO-8859-1").

Por ejemplo, si deseas almacenar en un archivo llamado "nombre_archivo.properties" los valores que se encuentren en el objeto properties:

properties.store(new BufferedWriter(new FileWriter("nombre_archivo.properties")), "Ejemplo Properties");

Ejemplo completo

final String PROPERTIES_FILE = "app.properties";
String language = "ES";
Calendar lastAccess = null;

Properties properties = new Properties();

try {
    properties.load(new BufferedReader(new FileReader(PROPERTIES_FILE)));
    language = properties.getProperty("language", "ES");
    //La fecha y hora del último acceso está guardado como tiempo en milisegundos
    long lastAccessInMillis = Long.valueOf(properties.getProperty("lastAccess"));
    lastAccess = Calendar.getInstance();
    lastAccess.setTimeInMillis(lastAccessInMillis);
} catch (Exception ex) {
    //Si hay algún error, por ejemplo que no exista el archivo de propiedades
    //  se dejan los valores predeterminados del language (ES) y lastAccess (null)
}

//Muestra en pantalla los valores de las variables language y lastAccess
System.out.println("Idioma: " + language);
if (lastAccess != null) {
    String strLastAccess = (DateFormat.getDateTimeInstance()).format(lastAccess.getTime());
    System.out.println("Ultimo acceso: " + strLastAccess);
} else {
    System.out.println("Es la primera vez que usa esta aplicación");
}

properties.setProperty("language", language);
//Toma el valor que se almacenará en la propiedad lastAccess 
//  en función de la hora actual, y en formato de milisegundos
lastAccess = Calendar.getInstance();
String lastAccessInMillis = String.valueOf(lastAccess.getTimeInMillis());
properties.setProperty("lastAccess", lastAccessInMillis);

try {
    //Crea el archivo de propiedades
    properties.store(new BufferedWriter(new FileWriter(PROPERTIES_FILE)), "Ejemplo Properties");
} catch (IOException ex) {
    System.out.println("Error: No se ha podido crear el archivo de propiedades");
}

Creación y edición desde NetBeans

Si utilizas el entorno de desarrollo NetBeans, puedes crear fácilmente un archivo properties desde el menú New > Other > Categories: Other > Properties File. al que puedes acceder desde el menú contextual del arbol del proyecto o de archivos.

prop01

Desde el mismo árbol de proyectos o archivos se puede desplegar el contenido de un archivo de propiedades, de manera que se puede mostrar también en forma de árbol las propiedades contenidas en el archivo. Abriendo el menú contextual sobre una de las propiedades, podrás acceder a algunas acciones que puedes realizar directamente sobre la propiedad seleccionada.

prop02

La opción Edit abrirá el contenido del archivo de propiedades como si se tratara de un editor de texto habitual, mientras que con la opción Open se mostrará el contenido del archivo de propiedades en un entorno particular para este tipo de archivos.

prop03 prop04

Además, desde el menú contextual del archivo de propiedades puedes elegir la opción Add > Property, que facilita la introducción de nuevas propiedades y valores.

prop05