Настройка строки Java VM.разделитель
кто-нибудь нашел способ указать Java line.separator
свойство при запуске виртуальной машины? Я думал о чем-то подобном:--3-->
java -Dline.separator="n"
но это не интерпретирует символ" n " как символ строки. Есть идеи?
3 ответов
попробуйте использовать java -Dline.separator=$'\n'
. Это должно сработать, по крайней мере, в Баш.
вот тестовый прогон:
aioobe@r60:~/tmp$ cat Test.java
public class Test {
public static void main(String[] args) {
System.out.println("\"" + System.getProperty("line.separator") + "\"");
}
}
aioobe@r60:~/tmp$ javac Test.java && java -Dline.separator=$'\n' Test
"
"
aioobe@r60:~/tmp$
Примечание:
выражение $''
использует функцию Bash ANSI-C Quoting. Он расширяет символы обратной косой черты, таким образом $'\n'
создает символ строки (код ASCII 10), заключенный в одинарные кавычки. См. руководство Bash, раздел 3.1.2.4 ANSI-C цитирование.
чтобы преодолеть разрыв между ответами aioobe и Божо, я бы также посоветовал не устанавливать line.separator
параметр при запуске JVM, поскольку это потенциально нарушает многие фундаментальные предположения, которые код JVM и библиотеки делает о среде, в которой выполняется. Например, если библиотека, от которой вы зависите, зависит от line.separator
чтобы сохранить файл конфигурации кросс-платформенным способом, вы только что нарушили это поведение. Да, это крайний случай, но это делает его еще более гнусными, когда, лет теперь возникает проблема, и теперь весь ваш код зависит от этой настройки, в то время как ваши библиотеки (правильно) предполагают, что это не так.
тем не менее, иногда эти вещи находятся вне вашего контроля, например, когда библиотека использует line.separator
и не предоставляет вам возможности явно переопределить это поведение. В таком случае вы застряли, переопределяя значение или что-то более болезненное, например, повторная реализация или исправление кода вручную.
для тех, ограниченные случаи, допустимо переопределить line.separator
, но мы должны следовать двум правилам:
- минимизировать область переопределения
- отменить переопределение независимо от того, что
оба эти требования хорошо обслуживается AutoCloseable
и try-with-resources синтаксис, поэтому я реализовал PropertiesModifier
класс, чисто обеспечивает.
/**
* 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);
}
}
мой случай использования был с Files.write()
, что является очень удобным методом, за исключением того, что он явно полагается на line.separator
. Обернув вызов Files.write()
Я могу четко указать разделитель строк, который я хочу использовать, не рискуя подвергать это воздействию каких-либо других частей моего приложения (обратите внимание, конечно, что это все еще не потокобезопасно).
try(PropertiesModifier pm = new PropertiesModifier("line.separator", "\n")) {
Files.write(file, ImmutableList.of(line), Charsets.UTF_8);
}