15

line.separatorVM の起動時に Java プロパティを指定する方法を見つけた人はいますか? 私は次のようなことを考えていました:

java -Dline.separator="\n"

ただし、これは「\n」を改行文字として解釈しません。何か案は?

4

3 に答える 3

17

を使用してみてください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引用を参照してください。

于 2010-09-14T13:00:21.820 に答える
5

aioobe と Bozho の回答の間のギャップを埋めるために、line.separatorJVM の起動時にパラメーターを設定しないことをお勧めします。これは、JVM とライブラリ コードが実行中の環境について行う多くの基本的な仮定を破る可能性があるためです。クロスプラットフォームの方法で構成ファイルを保存するために依存しているline.separator場合、その動作が壊れています。はい、それはエッジケースですが、今から数年後に問題が発生し、すべてのコードがこの微調整に依存しているのに対し、ライブラリは(正しく)それを想定している場合、それはさらに悪質になります。そうではありません。

line.separatorとは言っても、ライブラリが依存していて、その動作を明示的にオーバーライドする方法を提供していない場合など、これらのことは制御できない場合があります。このような場合、値をオーバーライドするか、コードを手動で再実装またはパッチするなど、より面倒なことに行き詰っています。

これらの限られたケースでは、オーバーライドline.separatorしても問題ありませんが、次の 2 つの規則に従う必要があります。

  1. オーバーライドの範囲を最小限に抑える
  2. 何があってもオーバーライドを元に戻す

これらの要件は両方ともAutoCloseabletry-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);
}
于 2014-05-14T00:25:57.783 に答える
3

もし私があなただったら、私はそれをしません。ラインセパレータはプラットフォーム固有であり、そのままにしておく必要があります。Windows専用またはLinux専用のファイルを作成する場合は、UNIX_LINE_SEPARATORどこかに定数を定義して、代わりにそれを使用してください。

于 2010-09-14T12:57:49.753 に答える