IText 5.5.11解析HTML元素:cp1250编码与三列布局配置求助
解决iText 5.5.11解析含中欧特殊字符的HTML为三列PDF的问题
我来帮你搞定这个难题——既要处理č、ž、ř这类中欧特殊字符的编码乱码问题,还要实现三列布局,同时还不能修改原HTML字符串对吧?下面是针对性的解决方案:
1. 解析时明确指定CP1250编码
iText 5的XMLWorker默认会用UTF-8解析HTML,如果你原HTML是CP1250编码的,必须在解析阶段明确指定编码,否则特殊字符肯定会乱码。
如果你用parseElementList方法,直接传入编码参数即可:
// 假设html是你要解析的CP1250编码字符串 ElementList elements = XMLWorkerHelper.parseElementList(html, "cp1250");
要是用parseXHtml结合写入器,得同时指定输入流的编码和字符集:
ByteArrayInputStream inputStream = new ByteArrayInputStream(html.getBytes("cp1250")); XMLWorkerHelper.getInstance().parseXHtml(writer, document, inputStream, Charset.forName("cp1250"));
2. 注册支持中欧字符的字体
光设置编码还不够,你得确保PDF用的字体能识别č、ž、ř这些字符——默认的Helvetica字体不包含中欧字符,这也是很多人忽略的乱码原因。
你可以注册本地支持CP1250的字体(比如Windows系统里的ArialCE.ttf,或者开源的LiberationSans系列字体),然后在解析时指定字体提供者:
// 注册字体,替换成你本地字体的实际路径 FontFactory.register("C:/Windows/Fonts/arialce.ttf", "ArialCE"); // 创建自定义字体提供者,避免默认字体查找逻辑 XMLWorkerFontProvider fontProvider = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS); fontProvider.register("C:/Windows/Fonts/arialce.ttf"); // 解析时同时传入编码和字体提供者 ElementList elements = XMLWorkerHelper.parseElementList( html, "cp1250", fontProvider );
3. 用ColumnText实现三列布局
解析得到元素列表后,你可以用iText的ColumnText类把元素分配到三列中绘制,完美实现三列布局:
Document document = new Document(PageSize.A4); PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("three-column.pdf")); document.open(); // 先按前面的方法解析得到元素列表 ElementList elements = XMLWorkerHelper.parseElementList(html, "cp1250", fontProvider); // 计算三列的尺寸和位置 float pageWidth = document.getPageSize().getWidth(); float marginLeft = document.leftMargin(); float marginRight = document.rightMargin(); float marginTop = document.topMargin(); float marginBottom = document.bottomMargin(); float columnWidth = (pageWidth - marginLeft - marginRight) / 3; // 三列的起始X坐标 float[] columnXs = { marginLeft, marginLeft + columnWidth, marginLeft + 2 * columnWidth }; float columnYTop = document.getPageSize().getHeight() - marginTop; float columnYBottom = marginBottom; ColumnText columnText = new ColumnText(writer.getDirectContent()); int elemIndex = 0; // 遍历每一列,填充元素 for (float x : columnXs) { columnText.setSimpleColumn( x, columnYBottom, x + columnWidth, columnYTop ); // 往当前列添加元素,直到列满或元素用完 while (elemIndex < elements.size()) { int status = columnText.addElement(elements.get(elemIndex)); if (ColumnText.hasMoreText(status)) { // 当前列已满,切换到下一列 break; } elemIndex++; } columnText.go(); // 重置ColumnText状态,准备下一列 columnText.setText(null); } document.close();
关键注意点
- 先确认原HTML的编码确实是CP1250,可以用Notepad++这类工具查看编码格式,避免编码不匹配的问题。
- 字体文件要确保可访问,打包项目时记得把字体文件一起打包,或者使用内嵌字体(添加
BaseFont.EMBEDDED参数),避免在其他机器上显示异常。
内容的提问来源于stack exchange,提问作者Martin Závodný
相关产品推荐
相关产品推荐

