ljzsdut
GitHubToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

Linux安装字体

Linux安装字体

前言

近期在项目开发中,遇到一个问题。alpine作为基础镜像的docker容器里,java程序将word转换为pdf,或者产生验证码时,就报错。

java.lang.NullPointerException: null 
	at sun.awt.FontConfiguration.getVersion(FontConfiguration.java:1264) 
	at sun.awt.FontConfiguration.readFontConfigFile(FontConfiguration.java:219) 
	at sun.awt.FontConfiguration.init(FontConfiguration.java:107) 
	at sun.awt.X11FontManager.createFontConfiguration(X11FontManager.java:774) 
	at sun.font.SunFontManager$2.run(SunFontManager.java:431) 
	at java.security.AccessController.doPrivileged(Native Method) 
	at sun.font.SunFontManager.<init>(SunFontManager.java:376) 
	at sun.awt.FcFontManager.<init>(FcFontManager.java:35) 
	at sun.awt.X11FontManager.<init>(X11FontManager.java:57) 
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) 
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423) 
	at java.lang.Class.newInstance(Class.java:442) 
	at sun.font.FontManagerFactory$1.run(FontManagerFactory.java:83) 
	at java.security.AccessController.doPrivileged(Native Method) 
	at sun.font.FontManagerFactory.getInstance(FontManagerFactory.java:74) 
	at java.awt.Font.getFont2D(Font.java:491) 
	at java.awt.Font.access$000(Font.java:224) 
	at java.awt.Font$FontAccessImpl.getFont2D(Font.java:228) 
	at sun.font.FontUtilities.getFont2D(FontUtilities.java:180) 
	at sun.java2d.SunGraphics2D.checkFontInfo(SunGraphics2D.java:670) 
	at sun.java2d.SunGraphics2D.getFontInfo(SunGraphics2D.java:831) 
	at sun.java2d.pipe.GlyphListPipe.drawString(GlyphListPipe.java:50) 
	at sun.java2d.SunGraphics2D.drawString(SunGraphics2D.java:2926) 
	at com.rcyj.common.utils.code.ImageCodeUtil.generateCodeAndPic(ImageCodeUtil.java:82) 
	at com.rcyj.system.controller.SysSmsController.getImg(SysSmsController.java:136) 
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
	at java.lang.reflect.Method.invoke(Method.java:498) 
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) 
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) 
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104) 
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:892) 
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797) 
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) 
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1039) 
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942) 
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005) 
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897) 
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:645) 
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882) 
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:750) 
	at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74) 
	at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129) 
	at com.github.xiaoymin.swaggerbootstrapui.filter.SecurityBasicAuthFilter.doFilter(SecurityBasicAuthFilter.java:84) 
	at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) 
	at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) 
	at com.github.xiaoymin.swaggerbootstrapui.filter.ProductionSecurityFilter.doFilter(ProductionSecurityFilter.java:53) 
	at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) 
	at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) 
	at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:124) 
	at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) 
	at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) 
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) 
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109) 
	at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) 
	at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) 
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92) 
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109) 
	at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) 
	at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) 
	at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93) 
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109) 
	at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) 
	at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) 
	at org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:151) 
	at org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:85) 
	at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) 
	at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) 
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) 
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109) 
	at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) 
	at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) 
	at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84) 
	at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62) 
	at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68) 
	at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) 
	at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:132) 
	at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57) 
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) 
	at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46) 
	at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64) 
	at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60) 
	at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77) 
	at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43) 
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) 
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) 
	at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:292) 
	at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:81) 
	at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:138) 
	at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:135) 
	at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48) 
	at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43) 
	at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:272) 
	at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81) 
	at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:104) 
	at io.undertow.server.Connectors.executeRootHandler(Connectors.java:364) 
	at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830) 
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) 
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) 
	at java.lang.Thread.run(Thread.java:748) 

原因

经分析是缺少必要的字体。alpine默认没有安装任何字体。

字体通常存在版权问题。linux上字体比较少。中文字体更是基本不会安装。

alpine作为一个精简系统,更不会安装任何字体。

该镜像没有我需要的宋体。因此下面我来介绍下如何安装宋体。

linux字体

字体安装

linux字体使用的与windows一样,所以我们可以把字体文件拷贝到linux相关的目录即可。字体通常存在以ttf和ttc为后缀的2个文件,只需要其中一个即可。

linux字体管理软件是fontconfig,可以使用如下命令进行安装:

#centos
yum install -y fontconfig

#alpine
apk add fontconfig

#此外alpine有一款专门为其设计的英文字体ttf-dejavu,安装:apk add ttf-dejavu

字体查看

查看所有字体:

bash-4.4# fc-list
/usr/share/fonts/ttf-dejavu/DejaVuSansCondensed-Oblique.ttf: DejaVu Sans,DejaVu Sans Condensed:style=Condensed Oblique,Oblique
/usr/share/fonts/ttf-dejavu/DejaVuSerif-BoldItalic.ttf: DejaVu Serif:style=Bold Italic
/usr/share/fonts/SimSun.ttf: SimSun,宋体:style=Regular
/usr/share/fonts/ttf-dejavu/DejaVuLGCSerifCondensed-Italic.ttf: DejaVu LGC Serif,DejaVu LGC Serif Condensed:style=Condensed Italic,Italic
/usr/share/fonts/ttf-dejavu/DejaVuLGCSerifCondensed.ttf: DejaVu LGC Serif,DejaVu LGC Serif Condensed:style=Condensed,Book
......省略若干......
/usr/share/fonts/ttf-dejavu/DejaVuLGCSansCondensed-Bold.ttf: DejaVu LGC Sans,DejaVu LGC Sans Condensed:style=Condensed Bold,Bold
/usr/share/fonts/ttf-dejavu/DejaVuLGCSerifCondensed-BoldItalic.ttf: DejaVu LGC Serif,DejaVu LGC Serif Condensed:style=Condensed Bold Italic,Bold Italic
/usr/share/fonts/ttf-dejavu/DejaVuLGCSansMono-Oblique.ttf: DejaVu LGC Sans Mono:style=Oblique

查看已经安装的中文字体:

bash-4.4# fc-list :lang=zh
/usr/share/fonts/SimSun.ttf: SimSun,宋体:style=Regular
bash-4.4#

查看字体目录:

/usr/share/fonts
#字体可以放在其子目录下,例如中文字体我们可以放在:/usr/share/fonts/chinese

启用字体

重启容器即可启用新字体。 也可以执行下面的命令,启用新字体。

fc-cache

安装字体

字体文件window系统和linux系统是通用的,因此可以直接在win10上复制需要的字体文件,在小娜搜索框搜索字体,然后复制字体文件到/usr/share/fonts/目录下即可使用字体了。

Centos7安装字体:https://blog.csdn.net/wlwlwlwl015/article/details/51482065

yum -y install fontconfig	#安装字体库

yum -y install ttmkfdir	mkfontscale	#安装字体索引信息

建立字体缓存,命令如下:
cd /usr/share/fonts/chinese/; mkfontscale; mkfontdir; fc-cache -fv,执行完毕之后,字体就安装好了

提示

ttf和ttc的异同: 下载的字体一般是ttc或ttf格式的,系统显示这都是TrueType类型的字体。ttf格式的字体可以正常使用,但ttc的字体只有一些常用的汉字。 TTC是几个TTF合成的字库,安装后字体列表中会看到两个以上的字体。两个字体中大部分字都一样时,可以将两种字体做成一个TTC文件,现在常见的TTC中的不同字体,汉字一般没有差别,只是英文符号的宽度不一样,以便适应不同的版面要求