设置Java VM line.separator设置Java VM line.separator(S

2019-05-12 02:40发布

有没有人找到了一种方法如何指定Java line.separator上的VM启动属性? 我在想是这样的:

java -Dline.separator="\n"

但是,这并不interprete的“\ n”作为换行符。 有任何想法吗?

Answer 1:

尝试使用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-C报价 。 它扩大反斜杠转义字符,从而$'\n'产生一个换行(ASCII码10)字符,在单引号。 见击手册,节3.1.2.4 ANSI-C引用 。



Answer 2:

为了弥补aioobe和Bozho的答案之间的差距,我也建议不要设置line.separator在JVM启动参数,因为这可能会中断许多基本假设JVM和库代码使有关的环境中运行。例如,如果一个你依赖库依赖于line.separator为了存储配置文件在跨平台的方式,你刚刚打破这种行为。 是的,这是一个边缘的情况下,但是这使得它更加邪恶的时候,30年之后,一个问题不会突然出现,现在所有的代码依赖于这个调整到位是,当你的库(正确地)假设它不是。

这就是说,有时候这些东西是你无法控制,当库依赖于类似的line.separator并没有提供任何方法可以让你重写该行为作了明确规定。 在这种情况下,你坚持重写值,或一些更痛苦像重新实现或手动补丁代码。

对于那些有限的情况下,这是可以接受的覆盖line.separator ,但我们必须遵循两个规则:

  1. 最小化覆盖范围
  2. 恢复倍率不管是什么

这些要求都深受供应AutoCloseable和尝试,以资源的语法,所以我已经实现了一个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);
}


Answer 3:

我不会做,如果我是你。 该行分隔符是特定于平台,并应继续这样做。 如果你只想窗口写或只Linux的文件,定义一个UNIX_LINE_SEPARATOR不变的地方,并用它来代替。



文章来源: Setting Java VM line.separator