line.separator
VM の起動時に Java プロパティを指定する方法を見つけた人はいますか? 私は次のようなことを考えていました:
java -Dline.separator="\n"
ただし、これは「\n」を改行文字として解釈しません。何か案は?
line.separator
VM の起動時に Java プロパティを指定する方法を見つけた人はいますか? 私は次のようなことを考えていました:
java -Dline.separator="\n"
ただし、これは「\n」を改行文字として解釈しません。何か案は?
を使用してみてくださいjava -Dline.separator=$'\n'
。少なくともbashでは、これでうまくいくはずです。
テスト実行は次のとおりです。
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-CQuotingを使用します。バックスラッシュでエスケープされた文字を展開$'\n'
し、一重引用符で囲まれた改行(ASCIIコード10)文字を生成します。Bashマニュアルのセクション3.1.2.4ANSI-C引用を参照してください。
aioobe と Bozho の回答の間のギャップを埋めるために、line.separator
JVM の起動時にパラメーターを設定しないことをお勧めします。これは、JVM とライブラリ コードが実行中の環境について行う多くの基本的な仮定を破る可能性があるためです。クロスプラットフォームの方法で構成ファイルを保存するために依存しているline.separator
場合、その動作が壊れています。はい、それはエッジケースですが、今から数年後に問題が発生し、すべてのコードがこの微調整に依存しているのに対し、ライブラリは(正しく)それを想定している場合、それはさらに悪質になります。そうではありません。
line.separator
とは言っても、ライブラリが依存していて、その動作を明示的にオーバーライドする方法を提供していない場合など、これらのことは制御できない場合があります。このような場合、値をオーバーライドするか、コードを手動で再実装またはパッチするなど、より面倒なことに行き詰っています。
これらの限られたケースでは、オーバーライドline.separator
しても問題ありませんが、次の 2 つの規則に従う必要があります。
これらの要件は両方ともAutoCloseable
、try-with-resourcesPropertiesModifier
構文によって十分に満たされるため、両方を明確に提供するクラスを実装しました。
/**
* 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);
}
もし私があなただったら、私はそれをしません。ラインセパレータはプラットフォーム固有であり、そのままにしておく必要があります。Windows専用またはLinux専用のファイルを作成する場合は、UNIX_LINE_SEPARATOR
どこかに定数を定義して、代わりにそれを使用してください。