使用iText从html内容到pdf的阿拉伯字符

use*_*223 1 html pdf text arabic itext

我无法在PDF生成中将HTML内容中的阿拉伯字符显示为" "

我能够从String变量中显示阿拉伯语文本.同时我无法从HTML字符串生成阿拉伯语文本.

我想显示带有两列的PDF,左侧是英语,右侧是阿拉伯语文本.

当我使用以下程序转换为PDF格式.请帮助我这方面.

try
{
    Document document = new Document(PageSize.A4, 50, 50, 50, 50);
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    PdfWriter writer = PdfWriter.getInstance(document, out);
    BaseFont bf = BaseFont.createFont("C:\\arial.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
    Font font = new Font(bf, 8);
    document.open();

    BufferedReader br = new BufferedReader(new FileReader("C:\\style.css"));
    StringBuffer fileContents = new StringBuffer();
    String line = br.readLine();
    while (line != null)
    {
        fileContents.append(line);
        line = br.readLine();
    }
    br.close();
    String styles = fileContents.toString(); //"p { font-family: Arial;}"; 

    Paragraph cirNoEn = null;
    Paragraph cirNoAr = null;

    String htmlContentEn = null;
    String htmlContentAr = null;

    PdfPCell contentEnCell = new PdfPCell();
    PdfPCell contentArCell = new PdfPCell();

    cirNoEn = new Paragraph("Circular No. (" + cirEnNo + ")", new Font(bf, 14, Font.BOLD | Font.UNDERLINE));
    cirNoAr = new Paragraph("??? ??????? (" + cirArNo + ")", new Font(bf, 14, Font.BOLD | Font.UNDERLINE));

    htmlContentEn = “< p >< span > Dear….</ span ></ p >”;
    htmlContentAr = “< p >< span > ??? ??????? ??? ??????? </ p >< p > ??? ??????? ….</ span ></ p >”;
    for (Element e : XMLWorkerHelper.parseToElementList(htmlContentEn, styles))
    {
        for (Chunk c : e.getChunks())
        {
            c.setFont(new Font(bf));
        }
        contentEnCell.addElement(e);
    }
    for (Element e : XMLWorkerHelper.parseToElementList(htmlContentAr, styles))
    {
        for (Chunk c:e.getChunks())
        {
            c.setFont(new Font(bf));
        }
        contentArCell.addElement(e);
    }

    PdfPCell emptyCell = new PdfPCell();
    PdfPCell cirNoEnCell = new PdfPCell(cirNoEn);
    PdfPCell cirNoArCell = new PdfPCell(cirNoAr);

    cirNoEnCell.setHorizontalAlignment(Element.ALIGN_CENTER);
    cirNoArCell.setHorizontalAlignment(Element.ALIGN_CENTER);

    emptyCell.setBorder(Rectangle.NO_BORDER);
    emptyCell.setFixedHeight(15);

    cirNoEnCell.setBorder(Rectangle.NO_BORDER);
    cirNoArCell.setBorder(Rectangle.NO_BORDER);
    contentEnCell.setBorder(Rectangle.NO_BORDER);
    contentArCell.setBorder(Rectangle.NO_BORDER);

    cirNoArCell.setRunDirection(PdfWriter.RUN_DIRECTION_RTL);
    contentArCell.setRunDirection(PdfWriter.RUN_DIRECTION_RTL);

    contentEnCell.setNoWrap(false);
    contentArCell.setNoWrap(false);

    PdfPTable circularInfoTable = null;

    emptyCell.setColspan(2);
    circularInfoTable = new PdfPTable(2);
    circularInfoTable.addCell(cirNoEnCell);
    circularInfoTable.addCell(cirNoArCell);
    circularInfoTable.addCell(emptyCell);
    circularInfoTable.addCell(emptyCell);
    circularInfoTable.addCell(emptyCell);
    circularInfoTable.addCell(contentEnCell);
    circularInfoTable.addCell(contentArCell);
    circularInfoTable.addCell(emptyCell);

    circularInfoTable.getDefaultCell().setBorder(PdfPCell.NO_BORDER);
    circularInfoTable.setWidthPercentage(100);
    document.add(circularInfoTable);

    document.close();

}
catch (Exception e)
{

}
Run Code Online (Sandbox Code Playgroud)

Bru*_*gie 6

请查看ParseHtml7ParseHtml8示例.他们使用阿拉伯字符输入HTML输入,并使用相同的阿拉伯文字创建PDF:

包含HTML内容的PDF表格 PDF格式的HTML表格

在我们查看代码之前,请允许我解释在源代码中使用非ASCII字符不是一个好主意.例如:这没有完成:

 htmlContentAr = “<p><span> ??? ??????? ??? ???????</p><p>??? ??????? ….</span></p>”;
Run Code Online (Sandbox Code Playgroud)

您永远不会知道如何存储包含这些字形的Java文件.如果它没有存储为UTF-8,那么角色最终可能会看起来像完全不同的东西.已知版本控制系统存在非ASCII字符问题,甚至编译器也可能导致编码错误.如果您确实希望String在代码中存储硬编码值,请使用UNICODE表示法.您的部分问题是编码问题,您可以在此处阅读更多相关内容:生成PDF时无法获取捷克语字符

对于屏幕截图中显示的示例,我使用UTF-8编码保存了以下文件:

这是您在文件中找到的内容arabic.html:

<html>
<body style="font-family: Noto Naskh Arabic">
<p>??? ??????? ??? ???????</p>
<p>??? ???????</p>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)

这是您在文件中找到的内容arabic2.html:

<html>
<body style="font-family: Noto Naskh Arabic">
<table>
<tr>
<td dir="rtl">??? ??????? ??? ???????</td>
<td dir="rtl">??? ???????</td>
</tr>
</table>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)

问题的第二部分涉及字体.使用知道如何绘制阿拉伯字形的字体非常重要.很难相信arial.ttf你的C:驱动力根本就是正确的.那不是个好主意.我希望你使用C:/windows/fonts/arialuni.ttf哪些肯定知道阿拉伯字形.

选择字体是不够的.您的HTML需要知道要使用哪个字体系列.因为文档中的大多数示例都使用Arial,所以我决定使用NOTO字体.我通过阅读这个问题发现了这些字体:iText pdf在使用NOTO字体或Source Hans时不显示中文字符.我非常喜欢这些字体,因为它们很好并且(几乎)支持所有语言.例如,我使用的NotoNaskhArabic-Regular.ttf意思是我需要像这样定义字体familie:

style="font-family: Noto Naskh Arabic"
Run Code Online (Sandbox Code Playgroud)

我在我的XML的body标签中定义了样式,很明显你可以选择在哪里定义它:在外部CSS文件中,在标签<head>级别的样式部分中<td>,......这个选择完全是你的,但你必须定义哪个字体使用.

当然:当XML Worker遇到时font-family: Noto Naskh Arabic,iText不知道在哪里找到相应的,NotoNaskhArabic-Regular.ttf除非我们注册该字体.我们可以通过创建FontProvider接口实例来实现这一点.我选择使用XMLWorkerFontProvider,但您可以自由编写自己的FontProvider实现:

XMLWorkerFontProvider fontProvider = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS);
fontProvider.register("resources/fonts/NotoNaskhArabic-Regular.ttf");
Run Code Online (Sandbox Code Playgroud)

还有一个障碍:阿拉伯语是从右到左书写的.我看到您要在该级别定义运行方向,PdfPCell并使用a将HTML内容添加到此单元格ElementList.这就是我第一次写一个名为ParseHtml7的类似例子的原因:

public void createPdf(String file) throws IOException, DocumentException {
    // step 1
    Document document = new Document();
    // step 2
    PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
    // step 3
    document.open();
    // step 4
    // Styles
    CSSResolver cssResolver = new StyleAttrCSSResolver();
    XMLWorkerFontProvider fontProvider = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS);
    fontProvider.register("resources/fonts/NotoNaskhArabic-Regular.ttf");
    CssAppliers cssAppliers = new CssAppliersImpl(fontProvider);
    // HTML
    HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers);
    htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());
    // Pipelines
    ElementList elements = new ElementList();
    ElementHandlerPipeline pdf = new ElementHandlerPipeline(elements, null);
    HtmlPipeline html = new HtmlPipeline(htmlContext, pdf);
    CssResolverPipeline css = new CssResolverPipeline(cssResolver, html);

    // XML Worker
    XMLWorker worker = new XMLWorker(css, true);
    XMLParser p = new XMLParser(worker);
    p.parse(new FileInputStream(HTML), Charset.forName("UTF-8"));

    PdfPTable table = new PdfPTable(1);
    PdfPCell cell = new PdfPCell();
    cell.setRunDirection(PdfWriter.RUN_DIRECTION_RTL);
    for (Element e : elements) {
        cell.addElement(e);
    }
    table.addCell(cell);
    document.add(table);
    // step 5
    document.close();
}
Run Code Online (Sandbox Code Playgroud)

HTML中没有表格,但是我们创建了自己的表格PdfPTable,我们将HTML中的内容添加到PdfPCell运行方向LTR中,然后我们将此单元格添加到表格中,并将表格添加到文档中.

也许这是你的实际要求,但为什么你会这么复杂地做到这一点呢?如果您需要一个表,为什么不在HTML中创建该表并定义一些单元格是RTL,如下所示:

<td dir="rtl">...</td>
Run Code Online (Sandbox Code Playgroud)

这样,你不必创建一个ElementList,你可以像在ParseHtml8示例中那样将HTML解析为PDF :

public void createPdf(String file) throws IOException, DocumentException {
    // step 1
    Document document = new Document();
    // step 2
    PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
    // step 3
    document.open();
    // step 4
    // Styles
    CSSResolver cssResolver = new StyleAttrCSSResolver();
    XMLWorkerFontProvider fontProvider = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS);
    fontProvider.register("resources/fonts/NotoNaskhArabic-Regular.ttf");
    CssAppliers cssAppliers = new CssAppliersImpl(fontProvider);
    HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers);
    htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());

    // Pipelines
    PdfWriterPipeline pdf = new PdfWriterPipeline(document, writer);
    HtmlPipeline html = new HtmlPipeline(htmlContext, pdf);
    CssResolverPipeline css = new CssResolverPipeline(cssResolver, html);

    // XML Worker
    XMLWorker worker = new XMLWorker(css, true);
    XMLParser p = new XMLParser(worker);
    p.parse(new FileInputStream(HTML), Charset.forName("UTF-8"));;
    // step 5
    document.close();
}
Run Code Online (Sandbox Code Playgroud)

此示例中所需的代码较少,当您想要更改布局时,只需更改HTML即可.您无需更改Java代码.

还有一个例子:在ParseHtml9中,我在一列中创建了一个带有英文名称的表("Lawrence of Arabia"),在另一列中创建了阿拉伯语翻译("لورانسالعرب").因为我需要不同的英文和阿拉伯字体,我在这个<td>级别定义字体:

<table>
<tr>
<td>Lawrence of Arabia</td>
<td dir="rtl" style="font-family: Noto Naskh Arabic">?????? ?????</td>
</tr>
</table>
Run Code Online (Sandbox Code Playgroud)

对于第一列,使用默认字体,从左到右不需要特殊设置.对于第二列,我定义了一个阿拉伯字体,并将运行方向设置为"rtl".

结果如下:

阿拉伯语旁边的英语

这比你在代码中尝试做的要容易得多.

  • 您似乎对StackOverflow不熟悉.代码未添加到评论中.通过发布问题添加代码.您当前的问题得到了非常详细的回答,答案解决了问题中列出的问题.不幸的是,你没有接受它(你甚至没有投票).现在,您滥用评论部分发布与已回答问题无关的问题.如果我的初步答案(我花了宝贵时间的答案)不被赏识,为什么我会努力回答这些问题呢? (4认同)