java.util.logging 在 wsl 上中断,路径中有空格

java.util.logging breaks on wsl with spaces in paths

我有一个小型 Java 项目设置,其中包含 3 个文件 Foo.javalogging.propertiesbuild.gradle,如下所示。

Foo.java下面,我在运行下面

package foo;
import java.util.logging.Logger;

public class Foo {

    public static void  main(String[] args) {
        var file = Foo.class.getClassLoader().getResource("logging.properties").getFile();
        System.setProperty("java.util.logging.config.file", file);
        var l = Logger.getLogger(Foo.class.getName());
        l.info("HOLA!");
    }
}

对应的属性文件就是

handlers=java.util.logging.ConsoleHandler

gradle 文件很简单。

apply plugin: 'java'

sourceCompatibility = 11
targetCompatibility = 11

它们的结构如下

foo/
├─ src/
│  ├─ java/
│  │  ├─ main/
│  │  │  ├─ foo/
│  │  │  │  ├─ Foo.java
│  ├─ resources/
│  │  ├─ logging.properties
├─ build.gradle

到运行代码,我写

gradle build
java -cp build/classes/java/main/:build/resources/main/ foo.Foo

现在我的问题是:如果我在 /mnt/c/Users/Ludvig/Desktop/logtest/root 中找到 root,一切正常。如果我将路径更改为 /mnt/c/Users/Ludvig/Desktop/log test/root,则不会得到任何日志输出。请注意,它会默默地失败!所以程序 运行s,但是日志记录失败。怎么办?

的调用
Foo.class.getClassLoader().getResource("logging.properties")

returns a url,所以当调用 getFile 时,空格被 url 编码,路径变为 /mnt/c/Users/Ludvig/Desktop/log%20test/foo/build/resources/main/logging.properties。这不是 LogManager 可以为配置解析的路径,因此未成功设置日志记录。

调用 file = file.replace("%20", " ") 解决了问题。

然而,这似乎是一个丑陋的 hack,我希望看到针对此问题提出更好的解决方案。

我也非常感谢不会静默失败的解决方案...

您可以通过以下操作将 URL 转换为文件:

package foo;
import java.util.logging.Logger;
import java.io.File;

public class Foo {

    public static void  main(String[] args) throws Exception {
        var file = new File(Foo.class.getResource("logging.properties").toURI());
        System.setProperty("java.util.logging.config.file", file.getCanonicalPath());
        var l = Logger.getLogger(Foo.class.getName());
        l.info("HOLA!");
    }
}

您不必将 URL 转换为文件。 LogManager 支持 InputStream 对象,只要您的代码在任何其他代码 运行.

之前显式重新配置记录器
package foo;
import java.util.logging.Logger;

private static final Logger logger;
    static {
        try (InputStream in = Foo.class.getClassLoader().getResourceAsStream("logging.properties")) {
           //LogManager.getLogManager().readConfiguration(in); //JDK 8
           LogManager.getLogManager().updateConfiguration(in, (k) -> ((o, n) -> n)); //JDK 9+
        } catch(IOException ioe) {
           throw new ExceptionInInitializerError(ioe);
        }
     logger = Logger.getLogger(Foo.class.getName());
}

public class Foo {

    public static void  main(String[] args) throws Exception {
        logger.info("HOLA!");
    }
}