我能够从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) { }请查看 ParseHtml7和 ParseHtml8示例.他们使用阿拉伯字符输入HTML输入,并使用相同的阿拉伯文字创建PDF:
在我们查看代码之前,请允许我解释在源代码中使用非ASCII字符不是一个好主意.例如:这没有完成:
htmlContentAr = “<p><span> رقم التعميم رقم التعميم</p><p>رقم التعميم ….</span></p>”;
您永远不会知道如何存储包含这些字形的Java文件.如果它没有存储为UTF-8,那么角色最终可能会看起来像完全不同的东西.已知版本控制系统存在非ASCII字符问题,甚至编译器也可能导致编码错误.如果您确实希望在代码中存储硬编码的String值,请使用UNICODE表示法.您的部分问题是编码问题,您可以在此处阅读更多相关信息:Can’t get Czech characters while generating a PDF
对于屏幕截图中显示的示例,我使用UTF-8编码保存了以下文件:
这是你在文件arabic.html中可以找到的:
<html> <body style="font-family: Noto Naskh Arabic"> <p>رقم التعميم رقم التعميم</p> <p>رقم التعميم</p> </body> </html>
这是你在arabic2.html文件中找到的:
<html> <body style="font-family: Noto Naskh Arabic"> <table> <tr> <td dir="rtl">رقم التعميم رقم التعميم</td> <td dir="rtl">رقم التعميم</td> </tr> </table> </body> </html>
问题的第二部分涉及字体.使用知道如何绘制阿拉伯字形的字体非常重要.很难相信你的C:驱动器的根目录上有arial.ttf.那不是个好主意.我希望你使用C:/windows/fonts/arialuni.ttf,它肯定知道阿拉伯字形.
选择字体是不够的.您的HTML需要知道要使用哪个字体系列.因为文档中的大多数示例都使用Arial,所以我决定使用NOTO字体.我通过阅读这个问题发现了这些字体:iText pdf not displaying Chinese characters when using NOTO fonts or Source Hans.我非常喜欢这些字体,因为它们很好并且(几乎)支持所有语言.例如,我使用了NotoNaskhArabic-Regular.ttf,这意味着我需要像这样定义字体familie:
style="font-family: Noto Naskh Arabic"
我在我的XML的body标签中定义了样式,显然你可以选择在哪里定义它:在外部CSS文件中,在< head>的样式部分中,在< td>的级别上. tag,…这个选择完全属于你,但你必须定义哪个字体要使用.
当然:当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");
还有一个障碍:阿拉伯语是从右到左书写的.我看到您要在PdfPCell级别定义运行方向,并使用ElementList将HTML内容添加到此单元格.这就是我第一次写一个名为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(); }
HTML中没有表格,但是我们创建了自己的PdfPTable,我们将HTML中的内容添加到带有运行方向LTR的PdfPCell,然后我们将这个单元格添加到表格中,并将表格添加到文档中.
也许这是你的实际要求,但为什么你会这么复杂地做到这一点?如果您需要一个表,为什么不在HTML中创建该表并定义一些单元格是RTL,如下所示:
<td dir="rtl">...</td>
这样,您不必创建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(); }
此示例中所需的代码较少,并且当您想要更改布局时,只需更改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>
对于第一列,使用默认字体,从左到右不需要特殊设置.对于第二列,我定义了一个阿拉伯字体,并将运行方向设置为“rtl”.
结果如下:
这比你在代码中尝试做的要容易得多.