基本上,我要做的是在类路径中的目录中注册所有字体(.ttf)。与从IDE启动应用程序时相比,在作为jar文件运行时执行此操作要复杂得多。当我从IDE启动应用程序时,不会抛出任何异常,我可以立即使用字体。但是,当我通过jar文件启动应用程序时,它仍然注册字体,但它抛出了这个异常:
java.awt.FontFormatException: java.nio.BufferUnderflowException
at sun.font.TrueTypeFont.init(Unknown Source)
at sun.font.TrueTypeFont.<init>(Unknown Source)
at sun.font.TrueTypeFont.<init>(Unknown Source)
at sun.font.SunFontManager.createFont2D(Unknown Source)
at java.awt.Font.<init>(Unknown Source)
at java.awt.Font.createFont0(Unknown Source)
at java.awt.Font.createFont(Unknown Source)
at com.cyr1en.cgdl.util.FontUtil.lambda$registerAllFonts$1(FontUtil.java:65)
at java.util.ArrayList.forEach(Unknown Source)
at com.cyr1en.cgdl.util.FontUtil.registerAllFonts(FontUtil.java:63)
at com.cyr1en.test.Launcher.main(Launcher.java:20)但正如我所说,字体仍然注册,我仍然能够使用它。
这是我的注册功能:
public static void registerAllFonts(String fontsDir) {
try {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
final File jarFile = new File(FontUtil.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
if (FileUtil.isJarFile(jarFile)) {
JarFile jar = new JarFile(jarFile);
Enumeration<JarEntry> entries = jar.entries();
ArrayList<JarEntry> jarEntries = Collections.list(entries);
List<JarEntry> fonts = jarEntries.stream().filter(f -> f.getName().startsWith(fontsDir)).collect(Collectors.toList());
fonts.forEach(f -> {
try {
ge.registerFont(Font.createFont(Font.TRUETYPE_FONT, jar.getInputStream(f)));
} catch (FontFormatException | IOException e) {
ExceptionUtil.generateErrorLog(e);
}
});
jar.close();
} else {
URL url = FontUtil.class.getResource(fontsDir);
if (url != null) {
File file = new File(url.toURI());
if (file.listFiles() != null)
for (File f : file.listFiles()) {
ge.registerFont(Font.createFont(Font.TRUETYPE_FONT, f));
}
}
}
} catch (IOException | FontFormatException | URISyntaxException e) {
ExceptionUtil.generateErrorLog(e);
}
}发布于 2018-05-26 08:01:37
我在filter()中的谓词包含实际的字体目录本身。因此,在列表中,我得到了fonts/、fonts/font1.ttf、fonts/font2.ttf,当然您不能从fonts/创建字体。
因此,解决方案是将谓词编辑为:
.filter(f -> f.getName().startsWith(finalFontsDir) && !f.getName().equals(finalFontsDir))多亏了@Robin Green
编辑:
另外,由于将"fonts/"作为目录传递给class.getResource(fontsDir)而只对JarEntry#getName()起作用,所以函数也做了一些修改。因此,只要通过"/fonts/",当使用jar启动时,只需删除第一个/即可。
public static void registerAllFonts(String fontsDir) {
try {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
final File jarFile = new File(FontUtil.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
if (FileUtil.isJarFile(jarFile)) {
if(fontsDir.startsWith("/"))
fontsDir = fontsDir.substring(1);
JarFile jar = new JarFile(jarFile);
Enumeration<JarEntry> entries = jar.entries();
ArrayList<JarEntry> jarEntries = Collections.list(entries);
final String finalFontsDir = fontsDir;
List<JarEntry> fonts = jarEntries.stream()
.filter(f -> f.getName().startsWith(finalFontsDir) &&
!f.getName().equals(finalFontsDir))
.collect(Collectors.toList());
fonts.forEach(f -> {
try {
ge.registerFont(Font.createFont(Font.TRUETYPE_FONT, jar.getInputStream(f)));
} catch (FontFormatException | IOException e) {
e.printStackTrace();
}
});
jar.close();
} else {
URL url = FontUtil.class.getResource(fontsDir);
if (url != null) {
File file = new File(url.toURI());
if (file.listFiles() != null)
for (File f : file.listFiles()) {
ge.registerFont(Font.createFont(Font.TRUETYPE_FONT, f));
}
}
}
} catch (IOException | FontFormatException | URISyntaxException e) {
ExceptionUtil.generateErrorLog(e);
}
}https://stackoverflow.com/questions/50540130
复制相似问题