JFreeChart在linux系统或者docker容器中出现中文变成方框的解决方法

1. 背景

     因为需要用java做报表,发现JFreeChart很好用,但项目在容器中部署后发现,JFreeChart生成的图表中文变成一个个方框,查看资料知,这是由于linux系统中缺少字体导致,

很多文章都是建议修改服务器linux,忘里面添加字体,但是实际情况中有的时候你没有权限,或不能对系统文件进行修改,而且我试过也没有成功,所以尝试给出一种在项目中解决的办法,供大家参考。

2. 解决方案介绍

   2.1 既然系统没有字体,我们就从项目中自带字体,这里选择黑体(字体下载地址),然后把字体读取到系统的某个目录下,接着根据这个字体文件新建一个Font字体,供JFreeChart调用。(注意:项目打成jar后无法读取项目目录下的字体资源,必须通过getResourceAsStream)

复制代码
 1    private Font getFont(int style, Float size) {
 2         Font defFont = new Font("黑体", style, 19);
 3 
 4         try {
 5             File file = initFontFile();
 6             if (!file.exists()) {
 7                 return defFont;
 8             }
 9             Font nf = Font.createFont(Font.TRUETYPE_FONT, file);
10             nf = nf.deriveFont(style, size);
11             log.info("----------------------------nf.getFontName()" + nf.getName() +
12                     "----------------------------");
13             return nf;
14         } catch (Exception e) {
15             log.info(e.getMessage(), e);
16         }
17         return defFont;
18     }
19         private File initFontFile() throws IOException {
20         String fileName = "simhei.ttf";
21         String filepath = getUploadResource(fileName);
22 
23         log.info(filepath);
24         return new File(filepath);
25     }
26     public String getUploadResource(String fileName) throws IOException {
27         //若文件已存在,则返回的filePath中含有"EXIST",则不需再重写文件
28         String filePath = createFile(fileName);
29 
30         //文件不存在,则创建流输入默认数据到新文件
31         if (!filePath.contains("exist")) {
32             File file = new File(filePath);
33             try (OutputStream os = new FileOutputStream(file); InputStream is = getClass().getClassLoader().getResourceAsStream(fileName)) {
34                 //返回读取指定资源的输入流
35                 log.info(os.toString());
36                 int bytesRead = 0;
37                 log.info(String.valueOf(bytesRead));  //Avoid code vulnerability scanning
38                 byte[] buffer = new byte[1024];
39                 if (is != null) {
40                     while ((bytesRead = is.read(buffer, 0, 1024)) != -1) {
41                         os.write(buffer, 0, bytesRead);
42                     }
43                 } else {
44                     log.error("---------------------------InputStream is null" +
45                             "-------------------------------------");
46                 }
47             } catch (FileNotFoundException e) {
48                 log.info(e.getMessage(), e);
49             } catch (IOException e) {
50                 log.info(e.getMessage(), e);
51             }
52             return filePath;
53         }
54         return filePath.substring(5);
55     }
56 
57 
58     public static String createFile(String filename) {
59         String dirPath = System.getProperty("user.dir") + Constants.M_GUARD_PATROL + "/uploadFiles";
60         File dir = new File(dirPath);
61         dir.mkdirs();
62 
63         //create file
64         String filePath = dirPath + File.separator + filename;
65         File file = new File(filePath);
66         if (!file.exists()) {
67             try {
68                 file.createNewFile();
69             } catch (IOException e) {
70                 log.info(e.getMessage(), e);
71             }
72             return filePath;
73         }
74         return "exist" + filePath;
75     }
复制代码

    2.2 然后设置图表的各种属性的字体,不然就会出现方框。

复制代码
 1 JFreeChart chart = ChartFactory.createBarChart(record.getTitle(), "",
 2                 "", dataSet);
 3         // 周围的背景色
 4         chart.setBackgroundPaint(ChartColor.WHITE);
 5 
 6         // 设置标题字体,否则会显示乱码
 7         TextTitle title = chart.getTitle();
 8         title.setFont(getFont(Font.PLAIN, 13f));
 9 
10         CategoryPlot barPlog = (CategoryPlot) chart.getPlot();
11         chart.getLegend().setItemFont(getFont(Font.PLAIN, 12f));
12         //设置图例类别字体
13         CategoryAxis domainAxis = barPlog.getDomainAxis(); //水平底部列表
14         domainAxis.setLabelFont(getFont(Font.PLAIN, 12f)); //水平底部标题
15         domainAxis.setTickLabelFont(getFont(Font.PLAIN, 12f)); //垂直标题
16 
17         //设置柱状图样式颜色
18         ChartUtils.setBarRenderer(barPlog, true);
复制代码

3.【附录】关于获取jar包资源路径的问题

    这里使用getResourceAsStream方法

    3.1 假如你把字体文件simhei.ttf放在resource目录下,如下图所示

 

 你就可以这样写

1 InputStream is =getClass().getClassLoader().getResourceAsStream("simhei.ttf")

     3.2 假如你把字体文件simhei.ttf放在resource/fonts目录下,就要写成

1  InputStream is =getClass().getClassLoader().getResourceAsStream("fonts/simhei.ttf")

详细可以参考这边文章《Java中getResourceAsStream的用法

posted @   屠城校尉杜  阅读(2028)  评论(1编辑  收藏  举报
编辑推荐:
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示