You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中使用PDFBox生成含SQL查询的PDF时抛出异常问题

排查PDFBox生成PDF时的异常问题

先从你给出的两段代码里,梳理几个大概率导致执行期异常的点:

1. 字符串数组拼接方法append的潜在问题

  • 空数组/Null判断缺失:如果传入的a或b是null,调用a.length或b.length会直接抛出NullPointerException。比如当SQL查询没有返回结果,或者其中一个拼接数组为空时就会触发。
  • 子数组长度不一致风险:如果a和b的子数组(也就是每行数据)列数不一样,后续drawTable里取content[0].length作为总列数,会导致表格列数和实际数据不匹配,轻则内容错位,重则抛出数组越界异常。

修改后的append方法可以加上防护:

public static String[][] append(String[][] a, String[][] b){ 
    // 处理null情况,把null当作空数组
    String[][] safeA = (a == null) ? new String[0][] : a;
    String[][] safeB = (b == null) ? new String[0][] : b;
    
    // 检查列数是否一致
    if (safeA.length > 0 && safeB.length > 0) {
        int colsA = safeA[0].length;
        int colsB = safeB[0].length;
        if (colsA != colsB) {
            throw new IllegalArgumentException("两个数组的列数必须一致");
        }
    }
    
    String[][] result = new String[safeA.length + safeB.length][]; 
    System.arraycopy(safeA, 0, result, 0, safeA.length); 
    System.arraycopy(safeB, 0, result, safeA.length, safeB.length); 
    return result; 
}

2. 表格绘制方法drawTable的潜在问题

  • 空数据判断缺失:如果content是空数组(比如SQL查询无结果),content[0].length会抛出ArrayIndexOutOfBoundsException。必须先判断rows > 0再处理列数。
  • 文本添加环节的隐藏问题:你代码里“添加字符串内容”的部分没贴出来,但这是高频异常点:
    • 有没有提前设置字体?如果没调用contentStream.setFont(PDType1Font.HELVETICA, 12)这类方法,添加文本时会抛出异常。
    • 文本坐标计算是否正确?比如每个单元格的文本应该从margin + cellMargin,nexty + cellMargin的位置开始,而且要注意beginText()和endText()的包裹,否则会有状态异常。
  • 页面边界检查:如果传入的y值太小,导致y - tableHeight小于页面底部(一般是0),虽然不会直接抛异常,但可能导致内容被截断,甚至部分绘制操作触发坐标异常。

修改后的drawTable开头加上空数据防护,同时补全文本添加的示例:

public static void drawTable(PDPage page, PDPageContentStream contentStream, float y, float margin, String[][] content) throws IOException{ 
    final int rows = content.length; 
    // 空数据直接返回,避免异常
    if (rows == 0) {
        return;
    }
    final int cols = content[0].length; 
    final float rowHeight = 20.0f; 
    final float tableWidth = page.getMediaBox().getWidth() - (2.0f * margin); 
    final float tableHeight = rowHeight * (float)rows; 
    final float colWidth = tableWidth / (float)cols; 
    final float cellMargin = 2f; 

    // 设置字体(必须先设置,否则添加文本会抛异常)
    contentStream.setFont(PDType1Font.HELVETICA, 12);

    // 绘制行
    float nexty = y; 
    for(int i=0;i<=rows;i++){ 
        contentStream.moveTo(margin, nexty); 
        contentStream.lineTo(margin + tableWidth, nexty); 
        contentStream.stroke(); 
        nexty -= rowHeight; 
    } 
    // 绘制列
    float nextx = margin; 
    for(int i=0;i<=cols;i++){ 
        contentStream.moveTo(nextx, y); 
        contentStream.lineTo(nextx, y - tableHeight); 
        contentStream.stroke(); 
        nextx += colWidth; 
    } 
    // 添加字符串内容
    contentStream.beginText();
    float textY = y - rowHeight + cellMargin;
    for(int i=0; i<rows; i++){
        float textX = margin + cellMargin;
        for(int j=0; j<cols; j++){
            contentStream.newLineAtOffset(textX, textY);
            contentStream.showText(content[i][j] != null ? content[i][j] : "");
            // 重置文本位置,避免累加偏移
            contentStream.newLineAtOffset(-textX, -textY);
            textX += colWidth;
        }
        textY -= rowHeight;
    }
    contentStream.endText();
}

额外排查建议

如果修改后还是抛异常,建议:

  • 打印出完整的异常栈信息,这是定位问题的关键(比如是NPE、IO异常还是PDFBox的特定异常)。
  • 检查SQL查询结果转成二维数组的过程,有没有出现null的行或列,或者数据类型转换错误。

内容的提问来源于stack exchange,提问作者Shirwyn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:47:52