Per colmare il divario tra le risposte di aioobe e Bozho, vorrei anche sconsigliare l'impostazione del parametro line.separator
all'avvio di JVM, in quanto ciò interrompe potenzialmente molti presupposti fondamentali che la JVM e il codice della libreria generano sull'ambiente in esecuzione. Ad esempio, se una libreria da cui si dipende si basa su line.separator
per archiviare un file di configurazione in un modo multipiattaforma, hai appena infranto quel comportamento. Sì, è un caso limite, ma questo rende ancora più nefasto quando, da qualche anno a questa parte, si verifica un problema, e ora tutto il codice dipende da questo aggiustamento, mentre le tue librerie lo assumono (correttamente) non lo è.
Detto questo, a volte queste cose non sono sotto il tuo controllo, come quando una libreria si basa su line.separator
e non consente in alcun modo di ignorare esplicitamente tale comportamento. In tal caso, sei bloccato a prevalere sul valore, o qualcosa di più doloroso come re-implementare o applicare patch al codice manualmente.
In questi casi limitati, l'è accettabile per ignorare line.separator
, ma abbiamo avuto modo di seguire due regole:
- minimizzare la portata della sostituzione
- Ripristinare l'override non importa quale
Entrambi questi requisiti sono ben serviti da AutoCloseable
e dalla sintassi try-with-resources, quindi ho implementato una classe PropertiesModifier
che fornisce in modo pulito entrambi.
/**
* 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);
}
}
mio caso d'uso era con Files.write()
, che è un metodo molto conveniente, tranne che si basa esplicitamente line.separator
. Raggomando la chiamata a Files.write()
posso chiaramente specificare il separatore di linea che voglio usare, senza rischiare di esporlo a qualsiasi altra parte della mia applicazione (prendere nota ovviamente che questo non è ancora sicuro per i thread).
try(PropertiesModifier pm = new PropertiesModifier("line.separator", "\n")) {
Files.write(file, ImmutableList.of(line), Charsets.UTF_8);
}
Puoi provare \ r \ n –