如何在Apache POI中复用字体?寻求便捷获取已创建字体方案
Great question! This is a common pain point when working with Apache POI's font management—every call to workbook.createFont() creates a new font instance, even if the properties are identical. Not only does this waste resources during runtime, but reusing fonts after restarting your Java app can be a hassle. Let's break down some practical solutions, including an optimized version of your temporary fix, plus more elegant approaches:
1. Runtime Reuse: In-Memory Font Cache
The simplest and most efficient way to avoid duplicate fonts during your program's runtime is to maintain a font cache pool. Use a Map where the key is a unique identifier built from the font's properties (name, size, bold status, color, etc.), and the value is the pre-created Font object. Next time you need a font with the same properties, just pull it from the cache instead of creating a new one.
Here's a quick implementation:
private static final Map<String, Font> FONT_CACHE = new HashMap<>(); public static Font getOrCreateFont(Workbook workbook, String fontName, short fontSize, boolean isBold, short color) { // Create a unique key from all font attributes String key = String.format("%s-%d-%b-%d", fontName, fontSize, isBold, color); if (FONT_CACHE.containsKey(key)) { return FONT_CACHE.get(key); } Font font = workbook.createFont(); font.setFontName(fontName); font.setFontHeightInPoints(fontSize); font.setBold(isBold); font.setColor(color); FONT_CACHE.put(key, font); return font; }
This approach eliminates redundant font creation entirely while your app is running, and it's straightforward to use.
2. Persistent Reuse: Optimized CustomProperty Approach
Your idea of using CustomProperty to store font identifiers is solid—we can refine it to make font lookup after restart much smoother:
- When creating a font, add a unique
CustomPropertytag (like a human-readable ID) to it. - When loading an existing workbook later, iterate through fonts and match against this tag instead of checking every property.
Example code:
// Create a font with a unique identifier tag public static Font createTaggedFont(Workbook workbook, String fontId) { Font font = workbook.createFont(); // Set your desired font properties here (name, size, etc.) font.getCustomProperties().addProperty("FONT_UNIQUE_ID", fontId); return font; } // Retrieve a font by its unique ID from an existing workbook public static Font getFontByTag(Workbook workbook, String fontId) { for (int i = 0; i < workbook.getNumberOfFonts(); i++) { Font font = workbook.getFontAt(i); CustomProperties props = font.getCustomProperties(); if (props != null && fontId.equals(props.getProperty("FONT_UNIQUE_ID"))) { return font; } } return null; // Return null if no matching font found }
This makes post-restart font lookup far more efficient than checking every font's properties one by one.
3. Advanced: Reuse Fonts from a Template Workbook
If you consistently use a fixed set of fonts across multiple workbooks, create a template workbook with all your pre-configured fonts. Then, either:
- Create new workbooks based on this template, or
- Copy the pre-defined fonts from the template to new workbooks.
Here's a rough example of copying fonts:
// Load your pre-configured template workbook Workbook templateWorkbook = WorkbookFactory.create(new File("font-template.xlsx")); Workbook newWorkbook = new XSSFWorkbook(); // Copy all fonts from template to new workbook for (int i = 0; i < templateWorkbook.getNumberOfFonts(); i++) { Font templateFont = templateWorkbook.getFontAt(i); Font newFont = newWorkbook.createFont(); // Copy all relevant font properties newFont.setFontName(templateFont.getFontName()); newFont.setFontHeightInPoints(templateFont.getFontHeightInPoints()); newFont.setBold(templateFont.getBold()); newFont.setColor(templateFont.getColor()); // Add other properties as needed (italic, underline, etc.) }
This is perfect for scenarios where your font styles don't change often—set up the template once, and reuse it forever.
Quick Summary
- Use an in-memory cache for runtime font reuse (fastest, simplest).
- Opt for the tagged CustomProperty method if you need to reuse fonts across application restarts.
- Go with a template workbook if you have a fixed set of fonts for all your workbooks.
内容的提问来源于stack exchange,提问作者AFoeee

