java - 使用 iText 4.2.1 将 RTF 转换为 PDF 时遇到 NullPointerException

标签 java pdf itext rtf

有人向我提出一项要求,要求将动态 RTF 文档转换为 PDF,并在转换之前填充 RTF 中的所有属性。

按照此 blog post 中的确切示例,我在运行应用程序时遇到了 NullPointerException

注意:我知道 iText 上的 RTF 文档支持是 abandoned但它已被客户端使用。

确切的堆栈跟踪:

Exception in thread "main" java.lang.NullPointerException
    at com.lowagie.text.rtf.parser.destinations.RtfDestinationFontTable.importSystemFonts(RtfDestinationFontTable.java:571)
    at com.lowagie.text.rtf.parser.destinations.RtfDestinationFontTable.init(RtfDestinationFontTable.java:206)
    at com.lowagie.text.rtf.parser.destinations.RtfDestinationFontTable.setParser(RtfDestinationFontTable.java:190)
    at com.lowagie.text.rtf.parser.destinations.RtfDestinationMgr.addDestination(RtfDestinationMgr.java:184)
    at com.lowagie.text.rtf.parser.ctrlwords.RtfCtrlWordHandler.<init>(RtfCtrlWordHandler.java:175)
    at com.lowagie.text.rtf.parser.ctrlwords.RtfCtrlWordMap.<init>(RtfCtrlWordMap.java:607)
    at com.lowagie.text.rtf.parser.ctrlwords.RtfCtrlWordMgr.<init>(RtfCtrlWordMgr.java:93)
    at com.lowagie.text.rtf.parser.RtfParser.init(RtfParser.java:655)
    at com.lowagie.text.rtf.parser.RtfParser.convertRtfDocument(RtfParser.java:551)
    at za.co.sindi.utils.Prints.printToPDFWithIText(Prints.java:114)
    at za.co.sindi.utils.Prints.main(Prints.java:150)

源示例:

    public static void printToPDFWithIText() {
        InputStream input = null;
        OutputStream output = null;
        Document document = null;

        try {
            input = new BufferedInputStream(new FileInputStream(new File("C:/testPDF.rtf")));
            output = new BufferedOutputStream(new FileOutputStream(new File("C:/testPDF_" + System.nanoTime() + ".pdf")));
            document = new Document();
            PdfWriter.getInstance(document, output);
            document.open();
            RtfParser parser = new RtfParser(null);
            parser.convertRtfDocument(input, document); //NullPointerException is here (line 114)
            document.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (DocumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            if (input != null) {
                try {
                    input.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

            if (output != null) {
                try {
                    output.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

//          if (document != null && document.isOpen()) {
//              document.close();
//          }
        }
    }

如何解决这个问题?

最佳答案

罪魁祸首是 com.lowagie.text.rtf.parser.destinations.RtfDestinationFontTable 上的以下实现类:

private Properties getEnvironmentVariables() throws Throwable {
    Properties environmentVariables = new Properties();
    String operatingSystem = System.getProperty("os.name").toLowerCase();
    Runtime runtime = Runtime.getRuntime();
    Process process = null;
    if (operatingSystem.indexOf("windows 95") > -1
            || operatingSystem.indexOf("windows 98") > -1
            || operatingSystem.indexOf("me") > -1) {
        process = runtime.exec("command.com /c set");
    } else if ((operatingSystem.indexOf("nt") > -1)
            || (operatingSystem.indexOf("windows 2000") > -1)
            || (operatingSystem.indexOf("windows xp") > -1)
            || (operatingSystem.indexOf("windows 2003") > -1)
            || (operatingSystem.indexOf("windows vista") > -1)) {
        process = runtime.exec("cmd.exe /c set");
    } else {
        process = runtime.exec("env");
    }
    BufferedReader environmentStream = new BufferedReader(new InputStreamReader(process.getInputStream()));
    String inputLine = "";
    int idx = -1;
    while ((inputLine = environmentStream.readLine()) != null) {
        idx = inputLine.indexOf('=');
                inputLine.substring(idx + 1));
    }
}

显然,开发人员检查了从 Windows 95 到 Windows Vista 的 Windows 操作系统。他/她忘记检查 Windows 7 和 Windows 8 环境。

System.getProperty("os.name"); 在我的开发工作站上返回 Windows 7,因此 Runtime 尝试调用 env 进程,该进程存在于 Windows 环境中。由于这会引发 Throwable,因此会发生以下实例:

private void importSystemFonts() {
    Properties pr = null;
    try {
        pr = getEnvironmentVariables();
    } catch (Throwable e) {
    }
    String systemRoot = pr.getProperty("SystemRoot");
    Runtime runtime = Runtime.getRuntime();
    String fileSeperator = System.getProperty("file.separator");
    int r = FontFactory.registerDirectory(systemRoot + fileSeperator + "fonts");
}

如您所见,pr 字段最初为 null。现在,有罪的方法(已经提到过)抛出了一个异常,并且 importSystemFonts 没有做任何事情来满足它,尽管它捕获了它。因此,pr 仍为 nullString systemRoot = pr.getProperty("SystemRoot"); 行现在抛出 NullPointerException

我们如何解决这个问题?

在运行你的程序之前,你必须作一点欺骗:欺骗库它不是 Windows 7 或更高版本。就我而言,我将其设置为 Windows Vista

必须在执行代码之前放置:

System.setProperty("os.name", "Windows Vista");

现在,运行您的代码,您将看到异常消失。

注意:由于此类已被废弃,请自行承担使用它的风险。如果您仍在使用此版本的 iText,我发布此内容是为了帮助其他人。

关于java - 使用 iText 4.2.1 将 RTF 转换为 PDF 时遇到 NullPointerException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26654693/

相关文章:

iphone - 如何在 iPad 中获取实际的 pdf 页面大小?

java - 为什么使用 Java 套接字永远不会到达输入流的末尾?

java - 在 Spring Security 中实现 UserDetails 和 CredentialsContainer

javascript - 将 Openlayers map 另存为 PDF(离线版)

c# - 使用 iTextSharp、RSA 和 AES csp 时,CryptographicException,提供者类型与注册值不匹配

java - 如何向页面添加 HTML 页眉和页脚?

java - itextpdf 生成损坏的链接

java - 为什么我的数据没有持久化?

c# - 为什么我们需要观察者模式?

ios - 由 UIDocumentInteractionController (iOS 10.3) 打开时出现空白或半加载的 PDF