La forma correcta sería la de proporcionar a los usuarios un editor de archivos de propiedad (o un plug-in para su editor de texto favorito) que les permite entrar en el texto como texto puro y guardará el archivo en el formato de archivo de propiedad.
Si no lo desea, está definiendo efectivamente un nuevo formato para el mismo (o un subconjunto del) modelo de contenido como los archivos de propiedades.
llegar hasta el final y, de hecho especifique su formato, y luego pensar en una manera de cualquiera
- transformar el formato de la canónica, y luego usar esto para cargar los archivos, o
- analiza este formato y rellena un objeto
Properties
.
Ambos enfoques solo funcionarán directamente si realmente puede controlar la creación de su objeto de propiedad, de lo contrario tendrá que almacenar el formato transformado con su aplicación.
Entonces, veamos cómo podemos definir esto. El modelo de contenido de archivos de propiedades normales es simple:
- Un mapa de claves de cadena de valores de cadena, ambas cadenas Java que permite arbitrarias.
El escape que desea evitar sirve solo para permitir cadenas de Java arbitrarias, y no solo un subconjunto de éstas.
una frecuencia suficiente subconjunto sería:
- Un mapa de claves de cadena (que no contiene ningún espacio en blanco, o
:
=
) a valores de cadena (que no contiene ningún principio o al final de espacio en blanco o saltos de línea).
En su ejemplo dir = c:\mydir
, la clave sería dir
y el valor c:\mydir
.
Si queremos que nuestras claves y valores contengan cualquier caracter Unicode (aparte de los prohibidos), debemos usar UTF-8 (o UTF-16) como la codificación de almacenamiento, ya que no tenemos forma de escapar caracteres fuera de la codificación de almacenamiento. De lo contrario, US-ASCII o ISO-8859-1 (como archivos de propiedades normales) o cualquier otra codificación compatible con Java sería suficiente, pero asegúrese de incluir esto en su especificación del modelo de contenido (y asegúrese de leerlo de esta manera)
Como nos limitamos el modelo de contenido de manera que todos los caracteres "peligrosos" son fuera del camino, ahora podemos definir el formato de archivo simplemente como esto:
<simplepropertyfile> ::= (<line> <line break>)*
<line> ::= <comment> | <empty> | <key-value>
<comment> ::= <space>* "#" < any text excluding line breaks >
<key-value> ::= <space>* <key> <space>* "=" <space>* <value> <space>*
<empty> ::= <space>*
<key> ::= < any text excluding ':', '=' and whitespace >
<value> ::= < any text starting and ending not with whitespace,
not including line breaks >
<space> ::= < any whitespace, but not a line break >
<line break> ::= < one of "\n", "\r", and "\r\n" >
Cada \
que ocurre en cualquiera de las teclas o el valor ahora es una real barra invertida, nada que se escape de otra cosa. Por lo tanto, para transformarlo en el formato original, simplemente hay que doblarlo, como Grekz propuso, por ejemplo, en un lector de filtrado:
public DoubleBackslashFilter extends FilterReader {
private boolean bufferedBackslash = false;
public DoubleBackslashFilter(Reader org) {
super(org);
}
public int read() {
if(bufferedBackslash) {
bufferedBackslash = false;
return '\\';
}
int c = super.read();
if(c == '\\')
bufferedBackslash = true;
return c;
}
public int read(char[] buf, int off, int len) {
int read = 0;
if(bufferedBackslash) {
buf[off] = '\\';
read++;
off++;
len --;
bufferedBackslash = false;
}
if(len > 1) {
int step = super.read(buf, off, len/2);
for(int i = 0; i < step; i++) {
if(buf[off+i] == '\\') {
// shift everything from here one one char to the right.
System.arraycopy(buf, i, buf, i+1, step - i);
// adjust parameters
step++; i++;
}
}
read += step;
}
return read;
}
}
entonces podríamos pasar este lector a nuestro objeto Properties (o guardar el contenido a un nuevo archivo).
En su lugar, podríamos simplemente analizar este formato nosotros mismos.
public Properties parse(Reader in) {
BufferedReader r = new BufferedReader(in);
Properties prop = new Properties();
Pattern keyValPattern = Pattern.compile("\s*=\s*");
String line;
while((line = r.readLine()) != null) {
line = line.trim(); // remove leading and trailing space
if(line.equals("") || line.startsWith("#")) {
continue; // ignore empty and comment lines
}
String[] kv = line.split(keyValPattern, 2);
// the pattern also grabs space around the separator.
if(kv.length < 2) {
// no key-value separator. TODO: Throw exception or simply ignore this line?
continue;
}
prop.setProperty(kv[0], kv[1]);
}
r.close();
return prop;
}
De nuevo, usando Properties.store()
después de esto, podemos exportar en el formato original.
Gracias por esta pista. Creé una clase de utilidad estática para cargar y guardar archivos de propiedades, pero tu camino es mucho más limpio. Por cierto, eso es lo que se necesita para cargar un poco del archivo de propiedades de netbeans (como project.properties), especialmente cuando se usa el paquete de movilidad. – Snicolas