1.什么是charset?
charset 是 character set 的缩写,中文意思是字符集,它是计算机中用于定义字符与二进制编码对应关系的集合,决定了文本数据如何被存储、传输和显示。字符集的本质是建立字符(如字母、汉字、符号) 和二进制数字(0 和 1) 之间的映射规则,解决不同语言、不同符号在计算机中的统一表示问题。
Foxit PDF SDK中的Charset 是在使用系统字体构建一个字体对象时,常使用方法:foxit.common.Font.Font ( string name, int styles, Font.Charset charset, int weight)。其中charset 类型主要是区分各类语言的,charset是为了映射字体名用。如果设置错误,可能导致生成的文本内容乱码。
Foxit PDF SDK API文档中charset的类型如下图所示:
2.怎么判断当前该使用哪个charset?
如果是用于常见的中英文文本,配合已知能够支持中英文的字体,那么用e_CharsetGB2312即可。
如果涉及更多的语言种类,比如要用一个泰文的字体,在PDF中添加一段文本,可以按照以下方式:
a.需要先通过标准接口,找到支持该语言的字体:
java 上获取系统的全部字体,以及是否支持泰文的示例代码如下:
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.util.*;
import java.util.List;
public class SystemFontsGet {
// 常见字体的字符集映射(聚焦字体的字符集类型,而非编码)
private static final Map<String, String> FONT_CHARSET_MAP = new HashMap<>();
// 用于检测的字符(中文、日文、韩文、英文)
private static final char CHINESE_CHAR = '中'; // 中文标识字符
private static final char JAPANESE_CHAR = '日'; // 日文标识字符(平假名/汉字)
private static final char KOREAN_CHAR = '한'; // 韩文标识字符(谚文)
private static final char ENGLISH_CHAR = 'A'; // 英文标识字符
private static final char THAI_CHAR = 'ส'; //泰文
/**
* 检测字体是否能渲染指定字符(核心:判断字体是否包含该字符的字形)
* @param font 字体对象
* @param c 要检测的字符
* @return true=能渲染,false=不能渲染(使用默认字体替代)
*/
private static boolean canRenderChar(Font font, char c) {
// 获取字体的渲染上下文
FontRenderContext frc = new FontRenderContext(null, true, true);
// 获取字符的字形边界:如果边界为空,说明字体无法渲染该字符
Rectangle2D bounds = font.getStringBounds(String.valueOf(c), frc);
return font.canDisplay(c) && bounds.getWidth() > 0 && bounds.getHeight() > 0;
}
/**
* 获取字体支持的语言(基于字符渲染检测)
* @param font 字体对象
* @return 支持的语言描述
*/
private static String getSupportedLanguages(Font font) {
List<String> supported = new ArrayList<>();
// 检测英文(几乎所有字体都支持)
if (canRenderChar(font, ENGLISH_CHAR)) {
supported.add("英文");
}
// 检测中文
if (canRenderChar(font, CHINESE_CHAR)) {
supported.add("中文(简/繁)");
}
// 检测日文
if (canRenderChar(font, JAPANESE_CHAR)) {
supported.add("日文");
}
// 检测韩文
if (canRenderChar(font, KOREAN_CHAR)) {
supported.add("韩文");
}
if (canRenderChar(font, THAI_CHAR)) {
supported.add("泰文");
}
// 如果仅支持英文,补充说明“西欧语言”
if (supported.size() == 1 && supported.get(0).equals("英文")) {
supported.add("西欧语言(如法语、德语)");
}
return supported.isEmpty() ? "未知" : String.join("、", supported);
}
/**
* 读取系统所有字体信息
*/
public static List<Map<String, Object>> readSystemFonts() {
List<Map<String, Object>> fontList = new ArrayList<>();
// 获取本地图形环境的所有字体家族名称(去重)
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
String[] fontFamilyNames = ge.getAvailableFontFamilyNames();
// 遍历每个字体
for (String fontFamilyName : fontFamilyNames) {
try {
// 创建字体对象(常规样式,大小12)
Font font = new Font(fontFamilyName, Font.PLAIN, 12);
// 解析字体信息
String supportedLanguages = getSupportedLanguages(font);
// 封装信息
Map<String, Object> fontInfo = new LinkedHashMap<>();
fontInfo.put("fontFamilyName", fontFamilyName); // 字体家族名称
fontInfo.put("supportedLanguages", supportedLanguages); // 支持的语言
fontList.add(fontInfo);
} catch (Exception e) {
System.err.println("处理字体[" + fontFamilyName + "]时出错:" + e.getMessage());
}
}
return fontList;
}
public static void main(String[] args) {
// 读取字体信息
List<Map<String, Object>> fontList = readSystemFonts();
// 格式化输出
System.out.println("系统已安装字体列表(共" + fontList.size() + "个):");
System.out.println("------------------------------------------------------------------------------------------");
System.out.printf("%-30s %-30s%n",
"字体家族名称", "支持的语言");
System.out.println("------------------------------------------------------------------------------------------");
for (Map<String, Object> fontInfo : fontList) {
System.out.printf("%-30s %-30s%n",
fontInfo.get("fontFamilyName"),
fontInfo.get("supportedLanguages"));
}
}
}
b. 选取一个支持泰文的字体,比如“Microsoft Sans Serif”,从API文档中找到对应泰文的的charset类型 “e_CharsetThai”在代码中使用:
Font font=new Font("Microsoft Sans Serif", e_StylesSmallCap, e_CharsetThai, 0);