iText7高级教程之html2pdf——6.在pdfHTML中使用字体

news2024/11/24 4:52:38

  到目前为止,我们还没有花太多的精力来研究将HTML转换为PDF时使用的字体。我们知道Helvetica是iText在没有指定字体时使用的默认字体(第2章),我们知道如果需要嵌入字体,pdfHTML会附带一些内置字体(第4章),但我们还没有得到支持哪些字体的清晰概述。

  在阅读本章之前,您需要了解两件事:

  • “iText core”库支持Type1字体(.AAFM/.PFB)、旧的TrueType字体(.TTF)、具有Type1轮廓的OpenType字体(.otf)、具有TrueType轮廓的OpenType字体(.TTF)和TrueType集合(.ttc),以及Web开放字体格式(.woff)。
  • pdfHTML插件使用DefaultFontProvider,默认情况下,它只支持14种标准Type 1字体和内置于pdfHTML中的12种字体。您可以配置字体提供程序以支持更多字体。

  在本章中,我们将查看一些使用pdfHTML中提供的默认字体的示例,并将解锁对核心库支持的所有其他类型字体的访问。

1. 标准Type 1字体

  ISO 32000(第1部分和第2部分)第9.6.2.2节列出了标准Type 1类字体(也称为14种标准字体)。

Section 9.6.2.2: Standard Type 1 Fonts (Standard 14 Fonts)

  14种Type 1字体(称为14种标准字体)的PostScript名称如下:Times Roman、Helvetica、Courier、Symbol、Times Bold、Helvedica Bold、Courier Bold、ZapfDingbats、Times Italic、Helvetina Oblique、Courier Oblique,Times BoldItalic、Hervetica BoldOblique和Courier BoldObrique。

  这些字体或其字体度量(font metrics)和合适的替代字体应可供大家使用。

  在创建PDF文档时不必嵌入这些字体,因为每个PDF查看器都知道如何呈现这十四种字体。iText附带了与这些标准14字体对应的14个Adobe Font Metrics(AFM)文件,这意味着始终支持这些字体。但是,由于相应的打印机字体二进制文件(Printer Font Binaries,PFB)是专有的,iText永远不会嵌入这些字体。

  fonts_standardtype1.html文件列出了14种字体:4种Helvetica字体、4种Times字体、4种Courier字体、Symbol和ZapfDingbats字体。从图6.1中可以看出,浏览器正确渲染了Helvetica、Times和Courier。

图6.1 标准Type 1字体(HTML)

图6.1 标准Type 1字体(HTML)

  Symbol和ZapfDingbats是具有自定义编码的字体。他们不能很好地在HTML中展示。在常见问题解答FAQ中,我们将发现还有其他字体更适合符号,例如Symbol和ZapfDingbats中提供的字体。目前,我们z只能展示Symbol字体的数字(0123456789)和ZapfDingbats字体的不间断空格字符( )

  下面代码中,我们使用在之前篇章中简单的createPdf()/CreatePdf():

public void createPdf(String src, String dest) throws IOException {
    HtmlConverter.convertToPdf(new File(src), new File(dest));
}

  当我们查看图6.2所示的文档属性中的字体选项卡时,我们看到PDF文档中使用了所有14种字体。

图6.2 标准Type 1字体(PDF)<

图6.2 标准Type 1字体(PDF)

  这些字体都没有嵌入,因为iText只提供字体度量,而不提供字体二进制文件。字体由本地计算机上可用的字体替换。在这种情况下,Courier被CourierStd取代,Helvetica被ArialMT取代,Times Roman被TimesNewRomanPSMT取代。

  不同操作系统上的不同PDF查看器可能会使用其他字体作为“Actual Fon”。例如,当您想要创建PDF/A文档时,这可能会有问题。为了解决这个问题,pdfHTML插件附带了12种免费字体。

2. iText附带的字体

  pdfHTML插件支持三种字体家族的字体嵌入:sanserifmonospaced家族。对于每个font-family,有四种字体可用:常规字体、粗体字体、斜体(或倾斜)字体和粗体斜体(或粗体倾斜)字体。

  在fonts_shipped.html文件中,我们使用font-family:FreeSansfont-family:FreeSeriffont-family:Free Mono。我们也可以使用font-family:sansfont-family:seriffont-family:mono;这将导致同样的结果。我们使用字体weight:bold和字体style:italic的不同组合,以便显示每个font-family的四种字体。

图6.3 pdfHTML附带的字体(HTML)

图6.3 pdfHTML附带的字体(HTML)

  用来呈现这个HTML页面的浏览器不知道在哪里可以找到sans和monospaced字体;如上图图6.3

  这很遗憾,但创建的相应PDF看起来不错。

图6.3 pdfHTML附带的字体(PDF)

图6.4 pdfHTML附带的字体(PDF)

  查看图6.4中文档属性的字体面板,我们发现十二种字体中的每一种都有一个子集被嵌入,而Helvetica和HelveticaBold则完全没有嵌入。

  如果不更改字体提供程序,这26种字体(其中只有24种在HTML上下文中真正有用)是默认情况下支持的唯一字体。

  这是非常有限的,所以让我们来看看如何添加对更多字体的支持。例如:如果我们能够访问我们正在使用的操作系统提供的所有系统字体,这不是很好吗?

3. 系统字体

  在fonts_system.html文件,我们引入了诸如Calibri和Verdana等字体系列。在Windows计算机上编写本教程,浏览器可以正确呈现不同的Calibri和Verdana字体(参见图6.5),因为C:\Windows\fonts目录中提供了相应的字体程序。

图6.5 系统字体(HTML)

图6.5 系统字体(HTML)

  默认情况下,pdfHTML使用如下创建的DefaultFontProvider实例:

FontProvider provider = new DefaultFontProvider();

  此构造函数调用另一个以三个布尔值作为参数的构造函数。上述行相当于:

FontProvider provider = new DefaultFontProvider(true, true, false);

  该构造函数的每个布尔值都会导致注册特定类型的字体:

  1. registerStandardPdfFonts–将注册十四种标准Type 1字体,
  2. registerShippedFreeFonts–将注册十二种iText自带的字体,
  3. registerSystemFonts–将注册系统字体。

  registerStandardPdfFontsregisterShippedFreeFonts的默认值为true,因为这些字体几乎不需要任何资源。

  registerSystemFonts的默认值为false,因为当您将此值设置为true时,iText将搜索操作系统上包含系统字体的目录。这有一些缺点:

  1. 加载和选择字体可能耗时,并且
  2. 如果我们注册完整的目录,我们无法控制字体的添加顺序,
  3. 如果你偶然碰到了带有嵌入限制的字体,那你就倒霉了。

  但现在我们不必担心,我们还是更改字体提供程序以支持系统字体。下面示例中将所有布尔值设置为true,然后看看会发生什么。

public void createPdf(String src, String dest) throws IOException {
    ConverterProperties properties = new ConverterProperties();
    properties.setFontProvider(new DefaultFontProvider(true, true, true));
    HtmlConverter.convertToPdf(new File(src), new File(dest), properties);
}

  现在我们已经更改了ConverterProperties,我们几乎可以使用C:\Windows\Fonts中的任何字体。其中包括Calibri和Verdana系列的字体。这些字体的子集现在嵌入到PDF中,如图6.6所示。

图6.6 系统字体(PDF)

图6.6 系统字体(PDF)

  如果您正在另一个操作系统上工作,例如Linux,没有C:\Windows\Fonts目录,但这不是问题。

  iText尝试使用环境变量获取字体目录,并在此基础上搜索以下目录:

  • /usr/share/X11/fonts
  • /usr/X/lib/X11/fonts
  • /usr/openwin/lib/X11/fonts
  • /usr/share/fonts
  • /usr/X11R6/lib/X11/fonts
  • /Library/Fonts,以及
  • /System/Library/Fonts

  小心使用此系统字体功能。通常,让pdfHTML访问所有系统字体不是最好的选择。让我们看看一些替代方案。

4. web开放字体格式(Web Open Font Format fonts)

  Web开放字体格式是一种用于网页的字体格式。WOFF字体本质上是具有压缩和附加元数据的OpenType或TrueType字体。

  在fonts_woff.html文件,您可以看到我们如何定义SourceSerifPro字体系列的六种字体。

图6.7 Web开放字体格式(HTML)

图6.7 Web开放字体格式(HTML)

  首先,我们定义@font-face,例如:

@font-face {
    font-family: "SourceSerifPro-Regular";
    src: url("fonts/SourceSerifPro-Regular.otf.woff") format("woff");
}

  然后定义一个类选择器中使用字体,例如:

.regular {
    font-family: "SourceSerifPro-Regular";
}

  最终,我们在HTML中使用类选择器:

<td class="regular">quick brown fox jumps over the lazy dog</td>

  这个例子我们不会改变ConverterProperties

public void createPdf(String src, String dest) throws IOException {
    HtmlConverter.convertToPdf(new File(src), new File(dest));
}

  pdfHTML插件将自动下载WOFF字体(如图6.7右下角所示),并将这些字体的子集嵌入PDF中,如图6.8所示。

图6.8 Web开放字体格式(PDF)

图6.8 Web开放字体格式(PDF)

  如果您想将在互联网上网页转换为PDF,则特别欢迎对WOFF字体的支持,但请考虑到使用此方法时,HTML到PDF的转换过程可能会缓慢。字体是通过网络下载的,这通常会降低速度。

  最快的选项是将所选字体添加到字体提供程序。

5. 添加所选字体到字体提供程序

  在fonts_extra.html中,我们将语句"quick brown fox jumps over the lazy dog"写了3次:

  • 一次为字体家族Cardo的常规字体,
  • 一次为字体家族Cardo的加粗字体,但如果在任何情况下都找不到Cardo粗体,则将使用Times字体,
  • 一次为字体家族Cardo的倾斜字体,但如果在任何情况下都找不到Cardo斜体,则将使用Times字体。

  如图6.9所示:

图6.9 额外字体(HTML)

图6.9 额外字体(HTML)

  在代码里面我调整了字体提供程序:

public static final String FONT = "src/main/resources/fonts/cardo/Cardo-Regular.ttf";
public void createPdf(String src, String font, String dest) throws IOException {
    ConverterProperties properties = new ConverterProperties();
    FontProvider fontProvider = new DefaultFontProvider();
    FontProgram fontProgram = FontProgramFactory.createFont(FONT);
    fontProvider.addFont(fontProgram);
    properties.setFontProvider(fontProvider);
    HtmlConverter.convertToPdf(new File(src), new File(dest), properties);
}

  我们将执行以下步骤:

  • 我们创建一个DefaultFontProvider实例。
  • 通过传递指向字体程序Cardo-Regular.ttf路径给FontProgramFactory来创建一个FontProgram
  • 添加这个字体程序到字体提供程序,并且把这个字体提供程序设置成一个转换属性。

  通过这种方式,我们将一种选定的字体添加到字体提供程序中。因此,我们定义了常规字体的语句“quick brown fox jumps over the lazy dog”将使用Carbo-Regular字体呈现。由于我们没有提供Carbo系列的任何粗体或斜体字体,因此其他两行使用Type 1型字体Roman-Bold和Roman-Italic。

图6.10 额外字体(PDF)

图6.10 额外字体(PDF)

  让我们修复它,下面的例子中,我们不使用addFont()/AddFont()方法一次添加一个字体。相反,我们使用addDirectory()/AddDirectory()方法一次性添加三种Carbo字体:

public static final String FONTS = "src/main/resources/fonts/cardo/";
public void createPdf(String src, String fonts, String dest) throws IOException {
    ConverterProperties properties = new ConverterProperties();
    FontProvider fontProvider = new DefaultFontProvider();
    fontProvider.addDirectory(FONTS);
    properties.setFontProvider(fontProvider);
    HtmlConverter.convertToPdf(new File(src), new File(dest), properties);
}

   Cardo目录下面同时包含了字体家族Cardo的粗体和斜体,iText不再依赖于Times字体系列。如图6.11

图6.11 额外字体(PDF,都为Cardo字体家族)

图6.11 额外字体(PDF,都为Cardo字体家族)

  添加包含大量字体的目录时要小心。字体添加到字体提供程序的顺序很重要、

6. 选择正确的字体顺序

  当我们谈到使用系统字体时,我们提到,如果我们注册了完整的目录,就无法控制字体的添加顺序。我们将使用简单的hello.htmk文件了解为什么这是一个缺点。见图6.12

图6.12 Hello HTML,未指定字体

图6.12 Hello HTML,未指定字体

  我们将使用相同的createPdf()/CreatePdf()方法将这个简单的HTML文件转换为PDF两次,但我们将创建一个DefaultFontProvider实例,该实例不注册任何标准Type 1字体,不注册任何内置字体,也不注册任何系统字体。这将排除使用Helvetica、FreeSans或任何其他字体作为默认字体。

  我们将添加一组字体,这些字体的路径存储在名为fontsString数组中;pdfHTML必须使用其中一种字体作为默认字体。代码如下:

public void createPdf(String src, String[] fonts, String dest) throws IOException {
    ConverterProperties properties = new ConverterProperties();
    FontProvider fontProvider = new DefaultFontProvider(false, false, false);
    for (String font : fonts) {
        FontProgram fontProgram = FontProgramFactory.createFont(font);
        fontProvider.addFont(fontProgram);
    }
    properties.setFontProvider(fontProvider);
    HtmlConverter.convertToPdf(new File(src), new File(dest), properties);
}

  我们将在两个例子C06E07_ExtraFontsOrder1.java和C06E08_ExtraFontsOrder2.java中使用相同的字体: NotoSans-Regular.ttf 和Cardo-Regular.ttf,但是两个例子生产的PDF会不一样。

  第一个例子C06E07_ExtraFontsOrder1.java中,创建的顺序为:

public static final String[] FONTS = {
    "src/main/resources/fonts/noto/NotoSans-Regular.ttf",
    "src/main/resources/fonts/cardo/Cardo-Regular.ttf"
};

  Noto字体是数组中的第一个元素,它包含将HTML文件呈现为PDF所需的所有字形,因此不需要Cardo字体。见图6.13

图6.13 Hello HTML,Noto字体<

图6.13 Hello HTML,Noto字体

  第二个例子C06E08_ExtraFontsOrder2.java中,我们把顺序颠倒:

public static final String[] FONTS = {
    "src/main/resources/fonts/noto/Cardo-Regular.ttf",
    "src/main/resources/fonts/cardo/NotoSans-Regular.ttf"
};

  现在Carbo字体是数组中的第一个元素,它还包含将HTML文件呈现为PDF所需的所有字形,因此不需要Noto字体。见图6.14

图6.14 Hello HTML,Carbo字体

图6.14 Hello HTML,Carbo字体

  这两个例子解释了pdfHTML内部工作的一个重要方面。当pdfHTML需要将字符呈现为字形时,它将首先在HTML中搜索字体名称,并询问字体提供商是否有该名称可用的字体。如果找不到字体,或者没有提供字体名称,则pdfHTML将按照注册的顺序对注册到字体提供商的不同字体进行循环。一旦pdfHTML找到可以将字符呈现为字形的字体,它将使用该字体。
  当注册一个完整的目录时,例如通过包含所有系统字体,您无法控制不同字体程序添加到字体提供程序的顺序。这使得很难预测pdfHTML将使用哪种字体。如果您编写的应用程序可以迁移到不同的系统,这尤其有问题。不同的系统可能有不同的系统字体,这可能会导致PDF文档看起来完全不同,因为使用了不同的字体。字体目录中包含嵌入限制的字体也存在风险。当pdfHTML遇到这样的字体时,将引发异常。

  字体有一个重要的方面,到目前为止我们没有花任何精力去关注。当我们使用字体时,我们将HTML文件中的字符映射到PDF文档中的字形。a字符可以映射到字母a的不同可视化,例如’a’、‘a’或’a’,甚至’α’或“@”或任何其他字形,具体取决于所使用的编码。

  有关字体和编码的更多信息,请参阅iText7高级教程之构建基础块——1.引入字体。

7. 选择合适的编码

  使用标准Type 1字体时,iText使用Helvetica、Times和Courier字体系列的Winansi编码。Symbol和ZapfDingbats字体有自己的自定义编码。

  在Winansi编码的情况下,iText创建一个简单的字体(simple font)。简单字体最多可将256个字符映射到256个字形,这意味着每个字符只能包含一个字节。如果您希望在一种字体中支持256个以上的字符,则需要使用复合字体。例如:如果使用Identity-H编码,则字符将存储为Unicode字符。

  使用Unicode,或者至少提供到Unicode的映射(toUnicode mapping),被认为是PDF中的最佳实践。这是PDF/A level U的要求,也是可读性方面的要求,因为Unicode映射允许检索文件中引用的每个字符的语义属性。

  pdfHTML插件将尽可能使用Unicode。这解释了为什么许多示例在屏幕截图中显示Identity-H编码,但使用标准Type 1字体的情况除外。标准Type 1字体不支持Unicode,因此改用Winansi。

  如果您不同意iText选择的默认编码,可以定义自己的编码。例如,请见下面代码示例中,我们使用Carbo-Regular,就像我们在上一个示例中所做的那样,但是我们没有让iText选择编码,而是明确告诉iText使用Winansi:

public static final String FONT = "src/main/resources/fonts/cardo/Cardo-Regular.ttf";
public void createPdf(String src, String font, String dest) throws IOException {
    ConverterProperties properties = new ConverterProperties();
    FontProvider fontProvider = new DefaultFontProvider(false, false, false);
    FontProgram fontProgram = FontProgramFactory.createFont(FONT);
    fontProvider.addFont(fontProgram, "Winansi");
    properties.setFontProvider(fontProvider);
    HtmlConverter.convertToPdf(new File(src), new File(dest), properties);
}

  当我们将图6.15中文档属性的字体面板与图6.14中的字体面板进行比较时,我们现在看到的编码是“Ansi”而不是“Identity-H”。

图6.15 Hello HTML,Carbo字体,Ansi编码

图6.15 Hello HTML,Carbo字体,Ansi编码

  这种从复合字体到简单字体的变化也会影响文件大小。

  • 使用(Win)Ansi编码,每个字符存储为单个字节;
  • 使用Identity-H编码,每个字符都存储为两个字节。

  图6.16显示了fonts_cardo.pdf文件(Identity-H编码)和fonts_encoding.pdf文件(Ansi编码)的大小差异。

图6.16 复合字体vs简单字体

图6.16 复合字体vs简单字体

  文件大小的差异是有限的,因为包含单字节或双字节字符的内容流都是压缩的。

  如果文件大小有问题,可以考虑使用Winansi编码而不是Identity-H,但要注意这是有代价的。如果希望您你文件符合当前和未来的长期保存或可读性标准,最好创建文件大小稍大但使用Unicode的文件。

  如果要创建包含不同语言内容的文档,也可以使用Unicode。

8. 国际化

  fonts_i18n.html文件包含一个表,第一列是电影的英文标题,第二列是同一部电影的不同语言的标题。

图6.17 国际化(HTML代码

图6.17 国际化(HTML代码)

  我们使用UTF-8编码存储了此文件,并且在HTML标头中明确指出,此HTML文件中的所有字符都应视为UTF-8字符:

<meta charset="UTF-8">

  如果省略这一行,则会出现一个典型的编码问题,如图6.18所示。

图6.18 国际化(错误的浏览器视图)

图6.18 国际化(错误的浏览器视图)

  这绝对不是我们想要的。如果你像读取普通ASCII文件一样读取UTF-8文件,您可以在iText中获得类似的胡言乱语。如果使用正确的编码,您将看到如图6.19所示的页面。

图6.19 国际化(浏览器视图)

图6.19 国际化(浏览器视图)

  首先我们看看错误的代码示例,我简单的createPdf()/CreatePdf()方法是不够的。

public void createPdf(String src, String dest) throws IOException {
    HtmlConverter.convertToPdf(new File(src), new File(dest));
}

  在这个错误案例中主要有2大类陷阱,我们通过图6.20图6.21展示这些问题。

  当我们查看图6.20中的希伯来语(Hebrew )和阿拉伯语(Arabic)文本时,我们看到字符被呈现为字形,但它们的呈现顺序错误。希伯来语和阿拉伯语是从右到左书写的,需要额外的处理来检测和应用正确的书写系统。
图6.20 错误的国际化(PDF没有pdfCalligraph)

图6.20 错误的国际化(PDF没有pdfCalligraph)

  在“特殊”的书写系统中添加内容需要更多的CPU,出于性能的原因,iText默认情况下不使用该CPU。如果要转换希伯来语、阿拉伯语或印度语(印地语、卡纳达语、泰米尔语、泰卢固语…)内容,则需要在CLASSPATH中明确包含pdfCalligraph插件。这将激活特殊的排版功能。

  一旦安装了pdfCalligraph,希伯来文文本看起来已经更好了,但结果仍然存在一些严重问题,如图6.21所示。
图6.21 错误的国际化(PDF)

图6.21 错误的国际化(PDF)

  中文和韩语标题仍然缺失,日语标题中的几个字符也是如此。阿拉伯字符在那里,现在它们的顺序是正确的,但它们都是错误的,因为没有做连字。当您使用pdfCalligraph时,可以开箱即用地支持连字,但此插件使用存储在字体内部的信息来创建连字。不幸的是,内置字体不支持阿拉伯文连字。

  我们可以通过引入支持中文(如NotoSansCJKsc-Regular)、日语(如NotoSansCJKjp-Regular),韩语(如NotoSansCJKkr-Regular)、希伯来语(如NotoSansHebrew-Regular)和阿拉伯语(如NotoNaskhArabic-Regular)的字体来解决所有这些问题。你可以在包含Noto Sans常规字体的目录中找到所有这些字体。

  实现的代码如下:

public static final String[] FONTS = {
    "src/main/resources/fonts/noto/NotoSans-Regular.ttf",
    "src/main/resources/fonts/noto/NotoSans-Bold.ttf",
    "src/main/resources/fonts/noto/NotoSansCJKsc-Regular.otf",
    "src/main/resources/fonts/noto/NotoSansCJKjp-Regular.otf",
    "src/main/resources/fonts/noto/NotoSansCJKkr-Regular.otf",
    "src/main/resources/fonts/noto/NotoNaskhArabic-Regular.ttf",
    "src/main/resources/fonts/noto/NotoSansHebrew-Regular.ttf"
};
public void createPdf(String src, String[] fonts, String dest) throws IOException {
    ConverterProperties properties = new ConverterProperties();
    FontProvider fontProvider = new DefaultFontProvider(false, false, false);
    for (String font : FONTS) {
        FontProgram fontProgram = FontProgramFactory.createFont(font);
        fontProvider.addFont(fontProgram);
    }
    properties.setFontProvider(fontProvider);
    HtmlConverter.convertToPdf(new File(src), new File(dest), properties);
}

  现在,我们可以比较图6.22中使用pdfCalligraph创建的PDF的屏幕截图和图6.19中在浏览器中呈现的HTML页面。

图6.22 国际化(PDF)

图6.22 国际化(PDF)

  注意,我们明确排除了标准Type 1字体、内置字体和系统字体。我们完全优先考虑了Noto字体(google开源项目字体)。当然,我们没有使用与浏览器使用的字体完全相同的字体,但至少所有的字符都在那里,并且连字正确。如果我们想要更好的匹配,我们需要搜索浏览器使用的字体,并将相应字体程序的路径添加到字体提供程序。

实际上,官方提供的源码里面没有引入pdfCalligraph插件,因为这个插件是闭源的,书写顺序一致是从左到右,如果你对书写顺序感兴趣的话,你可以参阅 第7章-如何将包含阿拉伯语/希伯来语字符的HTML转换为PDF? 的内容

9. 总结

  在本章中,我们尝试了不同类型的字体。我们已经了解到,默认情况下只支持有限的字体集,而且我们可以添加对几乎任何我们喜欢的字体的支持,前提是我们可以访问相应的字体程序。

  我们还发现iText支持不同于西方从左到右书写系统的书写系统,并且支持连字(阿拉伯文、印度文……),但前提是我们包含pdfCalligraph插件。

  在下一章(也是最后一章)中,我们将讨论一些常见问题。

iText7高级教程之html2pdf教程源码下载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/46007.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

线下商家卖货难、拓客难、引流难,不如学习一下怎么结合O2O电商

大家好&#xff0c;我是阿璋&#xff0c;互联网行业中一直流传着这样的一句话&#xff0c;说的是“站在风口上&#xff0c;猪都能飞起来”。这句话的意思是&#xff0c;如果跟上了时代的发展&#xff0c;并且在时代发展的关键档口&#xff0c;那么在时代的推动下&#xff0c;也…

关系抽取(一)

关系抽取从流程上&#xff0c;可以分为流水线式抽取&#xff08;Pipline&#xff09;和联合抽取&#xff08;Joint Extraction&#xff09;两种&#xff0c;流水线式抽取就是把关系抽取的任务分为两个步骤&#xff1a;首先做实体识别&#xff0c;再抽取出两个实体的关系&#x…

Zookeeper(curator)实现分布式锁案例

文章目录一、搭建Zookeeper1、下载2、安装启动二、Zookeeper分布式锁简述三、curator客户端使用分布式锁1、curator概述2、curator使用四、测试效果1、几个常见命令1&#xff09;ls2&#xff09;stat3&#xff09;get4&#xff09;set2、加锁解锁效果3、竞争锁效果一、搭建Zook…

「区块链+数字身份」:DID 身份认证的新战场

美国经济学家布莱恩 • 阿瑟在其著作《技术的本质》中&#xff0c;写过这么一句话&#xff1a;「技术总是进行着这样一种循环&#xff0c;为解决老问题去采用新技术&#xff0c;新技术又引发新问题&#xff0c;新问题的解决又要诉诸更新的技术」。 区块链技术之所以能流行&…

金融外包测试项目经验分享

金融项目外包 测试管理 经验 软件测试 首先确定项目外包测试的核心问题—对项目外包测试的定位。 项目外包测试是一种服务性工作&#xff0c;所以把服务放在第一位是做任何事情的出发点。作为项目经理&#xff0c;一定要把这种思想告诉给我们的测试团队成员&#xff0c;树立服务…

webGL学习

1 初试webGL const canvas document.getElementById(canvas) //获取webgl上下文对象 相当于设置画笔 const gl canvas.getContext(webgl) //声明颜色 gl.clearColor(0,0,0,1)gl.clear(gl.COLOR_BUFFER_BIT)2 将rbga颜色设置为webgl颜色 使用three.js的color const color …

在一个已经EXIT的docker容器中,修改配置文件

文章目录背景一、方法一二、方法二1.通过运行docker inspect [容器id]来获取到底层的容器对象信息2.修改配置文件总结背景 当我们在修改容器里的配置文件后(例如mysql),发现重新运行容器起不来了,此时不要慌&#xff01;下面我来介绍两种方法来修改已经停止的容器里的配置文件,…

jvm监控服务性能、以及资源使用情况

目录 1.前言&#xff1a; 2.如何监控 2.1.spring admin 2.2.pass平台 2.3jvm 本地jdk监控本地服务 2.3.1介绍 2.3.2JVisualVM能做什么 2.3.3使用 2.4jvm 本地jdk监控远程服务 方式一 方式二 1.前言&#xff1a; 常规新项目上线&#xff0c;做非功能测试&#xff08…

【目标检测】Faster R-CNN的几点理解

目录&#xff1a;Faster R-CNN的几点理解一、Faster R-CNN概述二、R-CNN、Fast R-CNN、Faster R-CNN的对照2.1 R-CNN2.1.1 R-CNN的检测步骤2.1.2 R-CNN的主要缺点2.2 Fast R-CNN2.2.1 Fast R-CNN的检测步骤2.2.2 Fast R-CNN的缺点2.3 R-CNN、Fast R-CNN、Faster R-CNN的比较三、…

【Android App】获取照片里的位置信息及使用全球卫星导航系统(GNSS)获取位置实战(附源码和演示 超详细)

需要全部代码请点赞关注收藏后评论区留言私信~~~ 一、获取照片里的位置信息 手机拍摄的相片还保存着时间、地点、镜头参数等信息&#xff0c;这些信息由相片接口工具ExifInterface管理&#xff0c;它的常用方法说明如下&#xff1a; getLatLong&#xff1a;获取相片拍摄时候的…

双飞翼布局

实现双飞翼布局&#xff0c;两边保持不保&#xff0c;只有中间变化&#xff1a; html代码&#xff1a; ------------------------------------------------------------------------------------ <!doctype html> <html> <head> <meta charset"utf…

拼多多季报图解:营收355亿同比增65% 研发投入达27亿

雷递网 雷建平 11月28日拼多多今日发布2022年第三季度业绩报告。财报显示&#xff0c;拼多多2022年第三季度营收为355亿元&#xff0c;同比增长65.1%。受到一些项目投入延缓等偶发因素影响&#xff0c;三季度平台运营费用为176.5亿元&#xff0c;占收入的比例从上年同期的59.6&…

VH03型多功能采集仪

河北稳控科技手持振弦传感器VH03型多功能采集仪&#xff0c;是专用的多类型传感器手持式读数仪&#xff0c;主测传感类型为单弦式振弦传感器&#xff0c;辅测传感类型为电压、电流传感。采用32位ARM处理器和大尺寸全彩屏、阵列按键设计&#xff0c;在完成快速测读的同时还具备极…

高校排课系统/排课管理系统的设计与实现

摘 要 网络的广泛应用给生活带来了十分的便利。所以把高校排课与现在网络相结合&#xff0c;利用JSP技术建设高校排课系统&#xff0c;实现高校排课的信息化。则对于进一步提高高校排课发展&#xff0c;丰富高校排课经验能起到不少的促进作用。 高校排课系统能够通过互联网得到…

国民经济行业代码查询系统-公司行业代码查询

今天在申请公司的一些信息时&#xff0c;要我给公司行业的代码&#xff0c;4位&#xff0c;问了财务和高企的申请伙伴&#xff0c;都没有特别清晰&#xff0c;让百度&#xff0c;直接百度花了点时间&#xff0c;记录一下&#xff0c;帮助其他的伙伴 国民经济行业代码查询系统 …

Python的10个编程技巧,你不一定都知道

文末有Python资料下载 1. 原地交换两个数字 Python 提供了一个直观的在一行代码中赋值与交换&#xff08;变量值&#xff09;的方法&#xff0c;请参见下面的示例&#xff1a; 赋值的右侧形成了一个新的元组&#xff0c;左侧立即解析&#xff08;unpack&#xff09;那个&…

2022-安洵杯

WEB babyphp call_user_func() 函数如果传入的参数是array类型的话&#xff0c;会将数组的成员当作类名和方法&#xff0c; array(0) { } <?php //something in flag.phpclass A {public $a;public $b;public function __wakeup(){$this->a "babyhacker";…

Mathematica(36)-在Plot中画平行于y轴的线

在论文写作过程中&#xff0c;我们常常也需要画一条平行于y坐标轴的直线&#xff0c;怎么实现呢&#xff1f; 比如&#xff0c;下面的代码就是绘制了一条平行于y轴的直线&#xff0c;这条直线采用了虚线来表示 Plot[Sin[x], {x, 0, 2 Pi}, Epilog -> {Dashed, Line[{{5, -…

ISCSLP 2022 | AccentSpeech—从众包数据中学习口音来构建目标说话人的口音语音合成系统

构建带口音的语音合成系统可以增加语音合成的多样性和趣味性。然而不是每个人都能说多种口音。为了实现口音与说话人音色的自由组合&#xff0c;借助迁移学习技术&#xff0c;为没有口音数据的说话人构建口音合成系统&#xff0c;是实现“口音任意说”的有效途径。但是以往大多…

[网络工程师]-应用层协议-WWW与HTTP

1、WWW 万维网&#xff08;World Wide Web,WWW&#xff09;是一个规模巨大、可以互联的资料空间&#xff0c;该资料空间的资源依靠URL进行定位&#xff0c;通过HTTP协议传送给使用者&#xff0c;又由HTML进行文档的展现。由此可知&#xff0c;WWW的核心由三个主要标准构成&…