Caused by: java.io.FileNotFoundException: /app/mes-eflow-service-1.0.0-SNAPSHOT.jar!/BOOT-INF/classes!/Fonts/simhei.ttf (没有那个文件或目录)
时间: 2025-07-27 17:22:46 浏览: 9
<think>我们正在处理一个关于Java应用程序在运行时无法找到字体文件的问题,具体异常是`java.io.FileNotFoundException`,文件路径为`/BOOT-INF/classes!/Fonts/simhei.ttf`。这个路径看起来是在一个Spring Boot打包的JAR文件内部。根据引用[2]中的信息,Spring Boot应用在运行时是作为一个JAR文件执行的,因此我们不能使用常规的文件路径来访问JAR内的资源。我们需要使用Spring的`Resource`抽象来访问类路径下的资源。另外,引用[3]中提到了一个使用ffmpeg的例子,其中指定了字体文件的路径。虽然这个例子不是Java的,但它提醒我们在指定字体文件路径时需要注意路径的正确性。引用[4]提到了使用iText库处理PDF,但我们的问题不是关于iText的,因此可能不直接相关。引用[1]中的异常信息是关于ApachePDFBox的,它试图使用一个字体(Courier-BoldOblique)但该字体在指定的编码中不可用。这个异常与我们的问题类似,都是字体相关的问题,但具体原因不同。我们的问题是文件找不到,而引用[1]是字体可用性(编码)问题。因此,我们的解决方案应该是如何正确加载位于类路径(JAR文件内部)中的字体文件。步骤:1.使用Spring的`Resource`接口来获取字体文件的资源。2.由于字体文件在JAR内部,我们不能直接使用`File`对象,因为JAR中的资源不是一个单独的文件,而是一个流。因此,我们需要将资源作为流读取,然后使用`Font.createFont`方法加载字体。具体代码示例:假设字体文件位于类路径的`Fonts/simhei.ttf`下。我们可以这样加载:
```javatry {//使用ResourceLoader获取资源Resource resource= newClassPathResource("Fonts/simhei.ttf");InputStreaminputStream= resource.getInputStream();//创建字体Fontfont =Font.createFont(Font.TRUETYPE_FONT,inputStream);//使用字体// ...} catch(IOException| FontFormatExceptione){e.printStackTrace();
}```注意:`Font.createFont`需要传入字体文件的输入流。这样我们就可以从类路径中加载字体。另外,如果是在非Spring环境下,也可以使用`ClassLoader.getResourceAsStream`:```javaInputStreaminputStream= getClass().getClassLoader().getResourceAsStream("Fonts/simhei.ttf");
```但是,在Spring Boot应用中,推荐使用`ResourceLoader`(如上面的`ClassPathResource`)来加载资源。如果字体文件需要被多次使用,可以考虑将字体缓存起来,避免重复加载。另外,请确保字体文件确实被打包到了JAR文件中。可以检查生成的JAR文件,确认`Fonts/simhei.ttf`是否在`BOOT-INF/classes/`目录下。如果字体文件没有被打包进去,需要在构建配置(如Maven或Gradle)中确保资源文件被正确包含。总结:不要使用`File`来访问JAR内部的资源,而应该使用流的方式。相关问题:1.如何在SpringBoot中正确加载类路径下的资源文件?2.如何确保资源文件被正确打包到SpringBoot的JAR中?3.在Java中,如何动态加载并使用字体文件?</think>### Java 应用加载字体文件 `FileNotFoundException` 解决方案
当 Java 应用(尤其是 Spring Boot 应用)尝试加载打包在 JAR 内的字体文件(如 `/BOOT-INF/classes!/Fonts/simhei.ttf`)时,出现 `FileNotFoundException` 的根本原因是**无法直接通过文件路径访问 JAR 内部的资源**。以下是具体解决方案:
---
#### 解决方案 1:使用 `ClassPathResource` 加载字体流(推荐)
```java
import org.springframework.core.io.ClassPathResource;
import java.awt.Font;
import java.io.InputStream;
public Font loadFont() {
try {
// 使用 Spring 的 ClassPathResource 获取资源流
ClassPathResource resource = new ClassPathResource("Fonts/simhei.ttf");
InputStream fontStream = resource.getInputStream(); // ✅ 关键:通过流加载
// 创建字体对象
Font font = Font.createFont(Font.TRUETYPE_FONT, fontStream);
return font.deriveFont(12f); // 设置字体大小
} catch (Exception e) {
throw new RuntimeException("字体加载失败: " + e.getMessage());
}
}
```
**原理**:
JAR 内部的资源不是文件系统中的独立文件,而是压缩包中的条目。`ClassPathResource` 通过类加载器直接获取资源流,避免文件路径访问[^2]。
---
#### 解决方案 2:非 Spring 环境使用 `ClassLoader`
```java
InputStream fontStream = getClass().getClassLoader()
.getResourceAsStream("Fonts/simhei.ttf");
Font font = Font.createFont(Font.TRUETYPE_FONT, fontStream);
```
---
#### 验证字体是否被打包
1. **检查 JAR 结构**:
解压 JAR 文件,确认路径 `BOOT-INF/classes/Fonts/simhei.ttf` 是否存在:
```bash
jar tf your-app.jar | grep simhei.ttf
```
2. **Maven 配置**:
确保字体文件在 `src/main/resources` 目录下,Maven 会自动打包:
```text
src/main/resources/Fonts/simhei.ttf
```
---
#### 常见错误排查
1. **路径错误**:
资源路径 **不要** 包含 `BOOT-INF/classes!/`,直接使用相对路径 `Fonts/simhei.ttf`。
2. **字体初始化**:
`Font.createFont()` 后必须调用 `deriveFont()` 设置大小,否则字体无效。
3. **文件编码**:
确保字体文件名无中文或特殊字符(如 `simhei.ttf` 正确,`黑体.ttf` 可能异常)。
---
#### 其他框架的字体加载示例
- **Apache PDFBox**(引用[1]问题):
```java
PDType0Font.load(document, getClass().getResourceAsStream("/Fonts/simhei.ttf"));
```
- **FFmpeg 集成**(引用[3]场景):
需提前将字体文件**复制到外部目录**再调用,避免 JAR 路径问题。
---
阅读全文
相关推荐



















