【问题标题】:some special character is replace by '?' while generating pdf from html一些特殊字符被替换为“?”从html生成pdf时
【发布时间】:2015-07-21 08:36:09
【问题描述】:

我正在尝试使用 itextsharp 库从 html 文件生成 pdf,但我有一个问题,当我将 html 转换为 pdf 时,html 文件的某些特殊字符被替换为“?”符号。 (例如欧元)

这是我的代码:

var elements = XMLWorkerHelper.ParseToElementList(html, null);
foreach (var element in elements)
{    
    document.Add(element);
}

XMLWorkerHelper 是 itextsharp 库的一个类。 我只是希望我的 pdf 与我的 html 文件生成相同。

【问题讨论】:

  • 你能在某处设置编码吗?

标签: c# html itextsharp


【解决方案1】:

如果您使用XMLWorkerHelper.ParseToElementList(String, String)(您是),那么 iTextSharp 将通过调用 System.Text.Encoding.Default.GetBytes() 来要求 .Net 运行时找出文件的内容。

根据文档,System.Text.Encoding.Default

获取操作系统当前 ANSI 代码页的编码

进一步(强调我的):

不同的计算机可以使用不同的默认编码,甚至可以在一台计算机上更改默认编码。因此,从一台计算机流式传输到另一台计算机甚至在同一台计算机上的不同时间检索的数据可能翻译不正确。此外,默认属性返回的编码使用最佳回退将不受支持的字符映射到代码页支持的字符。由于这两个原因,一般不建议使用默认编码。为确保正确解码编码字节,您应该使用带有前导码的 Unicode 编码,例如 UTF8Encoding 或 UnicodeEncoding。另一种选择是使用更高级别的协议来确保编码和解码使用相同的格式。

所以从上面你会看到,在文件中没有任何关于如何解释原始字节的信息的情况下,.Net 将只使用本地 code page 来解释它们。真正有趣的是,如果您将代码 100% 完全按原样移动到另一台机器上,您可能会得到不同的结果,因为那台机器可能有不同的代码页集。

最好的解决方案是完全避免代码页。为此,只需将文件保存为 Unicode 兼容格式(如 UTF8)并包含 BOM 以明确声明您的意图。 BOM 是可选的(有些人不赞成),但在没有其他信息(例如 HTTP 标头或便利贴)的情况下,它也是最明确的方式。

第二种选择是使用适当的编码重新实现XMLWorkerHelper.ParseToElementList()。 SourceForge 显然现在已经关闭,所以这里是该方法的主体:

/**
 * Parses an HTML string and a string containing CSS into a list of Element objects.
 * The FontProvider will be obtained from iText's FontFactory object.
 * 
 * @param   html    a String containing an XHTML snippet
 * @param   css     a String containing CSS
 * @return  an ElementList instance
 */
public static ElementList ParseToElementList(String html, String css) {
    // CSS
    ICSSResolver cssResolver = new StyleAttrCSSResolver();
    if (css != null) {
        ICssFile cssFile = XMLWorkerHelper.GetCSS(new MemoryStream(Encoding.Default.GetBytes(css)));
        cssResolver.AddCss(cssFile);
    }

    // HTML
    CssAppliers cssAppliers = new CssAppliersImpl(FontFactory.FontImp);
    HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers);
    htmlContext.SetTagFactory(Tags.GetHtmlTagProcessorFactory());
    htmlContext.AutoBookmark(false);

    // Pipelines
    ElementList elements = new ElementList();
    ElementHandlerPipeline end = new ElementHandlerPipeline(elements, null);
    HtmlPipeline htmlPipeline = new HtmlPipeline(htmlContext, end);
    CssResolverPipeline cssPipeline = new CssResolverPipeline(cssResolver, htmlPipeline);

    // XML Worker
    XMLWorker worker = new XMLWorker(cssPipeline, true);
    XMLParser p = new XMLParser(worker);
    p.Parse(new MemoryStream(Encoding.Default.GetBytes(html)));

    return elements;
}

p.Parse 开头的倒数第二行代码是您要更改的内容。由于我们不知道您文件的字节数是什么(显然您的计算机也不知道),我们无法告诉您将编码器切换到什么位置。

总结一下,这实际上根本不是 iTextSharp 问题,这实际上是 .Net 运行时的默认行为。 iTextSharp 只是在没有信息的情况下使用系统默认值。

【讨论】:

    【解决方案2】:

    p.parse(new StringReader(html));

    这对我有用

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-16
      • 1970-01-01
      • 2017-08-12
      • 2019-03-20
      • 2019-11-04
      • 1970-01-01
      相关资源
      最近更新 更多