java.util.logging 在 wsl 上中断,路径中有空格
java.util.logging breaks on wsl with spaces in paths
我有一个小型 Java 项目设置,其中包含 3 个文件 Foo.java
、logging.properties
和 build.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!");
}
}
我有一个小型 Java 项目设置,其中包含 3 个文件 Foo.java
、logging.properties
和 build.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!");
}
}