2010-09-14 18 views
13

¿Alguien ha encontrado la manera de especificar la propiedad Java line.separator en el inicio de la máquina virtual? Estaba pensando en algo como esto:Configuración Java VM line.separator

java -Dline.separator="\n" 

pero esto no interprete la "\ n" como el carácter de avance de línea. ¿Algunas ideas?

+0

Puede probar \ r \ n –

Respuesta

13

Intente utilizar java -Dline.separator=$'\n'. Eso debería hacer el truco, al menos en bash.

Aquí está una ejecución de prueba:

[email protected]:~/tmp$ cat Test.java 
public class Test { 
    public static void main(String[] args) { 
     System.out.println("\"" + System.getProperty("line.separator") + "\""); 
    } 
} 
[email protected]:~/tmp$ javac Test.java && java -Dline.separator=$'\n' Test 
" 
" 
[email protected]:~/tmp$ 

Nota:

La expresión $'' utiliza la función Bash ANSI-C Citando. Se expanden los caracteres escapados de la barra invertida, por lo tanto, $'\n' produce un carácter de alimentación de línea (código ASCII 10), entre comillas simples. Vea el manual de Bash, sección 3.1.2.4 ANSI-C Quoting.

+0

Sí ... pero no deberías. –

+4

Definitivamente puedo ver cómo podría ser útil, por ejemplo, en un escenario de prueba. – aioobe

+0

Gracias, eso lo resolvió desde la línea de comandos. Todavía no funciona desde la configuración de ejecución de Eclipse IDE, pero eso no es importante. –

3

No haría eso si fuera tú. El separador de línea es específico de la plataforma y debería seguir siéndolo. Si desea escribir archivos solo de Windows o linux, defina una constante UNIX_LINE_SEPARATOR en algún lugar y úsela en su lugar.

+2

exactamente.algunas cosas no deberían ser cambiadas cualquier api que dependa de line.separator que tenga un valor específico se rompe –

+14

Me gustaría consultar si consideras que otras personas no son solo estúpidas sino que tienen sus razones. El mío es que se llama a un programa Java desde un script de shell. El script de shell usó stdout de la aplicación Java y la procesa aún más. Si ejecuta esa secuencia de comandos desde Cygwin, Java usa avances de línea de Windows. Sin embargo, eso causa problemas en el script. Por lo tanto, me gustaría cambiar el separador de línea predeterminado de Javas en caso de que se ejecute desde Cygwin. –

+1

primero, podría haber compartido estos detalles en la pregunta. En segundo lugar, ¿qué tiene de especial ese guión de shell que no se puede programar en Java? No me parece razonable tener un software java solo de Linux, que te guste ejecutar con Cygwin. Proporcione un archivo '.bat' (como Tomcat, por ejemplo) o mueva la funcionalidad a una clase Java. Y, por último, no considero a nadie estúpido. Pero las personas a menudo son inexpertas. – Bozho

4

Para cerrar la brecha entre aioobe y las respuestas de Bozho, también aconsejaría no configurar el parámetro line.separator en el arranque de JVM, ya que esto potencialmente rompe muchas suposiciones fundamentales que la JVM y el código de la biblioteca hacen sobre el entorno en el que se está ejecutando. Por ejemplo, si una biblioteca de la que depende se basa en line.separator para almacenar un archivo de configuración de forma multiplataforma, acaba de romper ese comportamiento. Sí, es un caso extremo, pero eso lo hace aún más nefasto cuando, dentro de unos años, surge un problema, y ​​ahora todo el código depende de que este ajuste esté en su lugar, mientras que sus bibliotecas lo están asumiendo (correctamente) no es

Dicho esto, a veces estas cosas están fuera de tu control, como cuando una biblioteca se basa en line.separator y no proporciona ninguna manera de anular ese comportamiento explícitamente. En tal caso, está atascado anulando el valor, o algo más doloroso como volver a implementar o parchear el código manualmente.

Para aquellos casos limitados, el que es aceptable para anular line.separator, pero tenemos que seguir dos reglas:

  1. minimizar el alcance de la anulación
  2. revertir la anulación no importa lo

Ambos requisitos están bien atendidos por AutoCloseable y la sintaxis try-with-resources, así que he implementado una clase PropertiesModifier que limpiamente proporciona ambos.

/** 
* Class which enables temporary modifications to the System properties, 
* via an AutoCloseable. Wrap the behavior that needs your modification 
* in a try-with-resources block in order to have your properties 
* apply only to code within that block. Generally, alternatives 
* such as explicitly passing in the value you need, rather than pulling 
* it from System.getProperties(), should be preferred to using this class. 
*/ 
public class PropertiesModifier implements AutoCloseable { 
    private final String original; 

    public PropertiesModifier(String key, String value) { 
    this(ImmutableMap.of(key, value)); 
    } 

    public PropertiesModifier(Map<String, String> map) { 
    StringWriter sw = new StringWriter(); 
    try { 
     System.getProperties().store(sw, ""); 
    } catch (IOException e) { 
     throw new AssertionError("Impossible with StringWriter", e); 
    } 
    original = sw.toString(); 
    for(Map.Entry<String, String> e : map.entrySet()) { 
     System.setProperty(e.getKey(), e.getValue()); 
    } 
    } 

    @Override 
    public void close() { 
    Properties set = new Properties(); 
    try { 
     set.load(new StringReader(original)); 
    } catch (IOException e) { 
     throw new AssertionError("Impossible with StringWriter", e); 
    } 
    System.setProperties(set); 
    } 
} 

Mi caso de uso estaba con Files.write(), que es un método muy conveniente, salvo que se basa explícitamente en line.separator. Envolviendo la llamada al Files.write() puedo especificar claramente el separador de línea que quiero utilizar, sin arriesgarme a exponer esto a otras partes de mi aplicación (tome nota, por supuesto, de que esto todavía no es seguro para subprocesos).

try(PropertiesModifier pm = new PropertiesModifier("line.separator", "\n")) { 
    Files.write(file, ImmutableList.of(line), Charsets.UTF_8); 
} 
Cuestiones relacionadas