JEditorPaneHTMLEditorKitParserNaN非数处理

wen java案例 2

本文目录导读:

JEditorPaneHTMLEditorKitParserNaN非数处理

  1. 核心原因
  2. 解决方案
  3. 常见的 NaN 出现场景
  4. 建议

这个问题看起来是关于 Java Swing 中 JEditorPane 搭配 HTMLEditorKit 解析 HTML 时,遇到 NaN(Not a Number)数值处理的问题。

NaN 出现在 HTML 中的数值属性里(CSS 的 width: NaNpxfont-size: NaN 或 JavaScript 动态生成的数值),HTMLEditorKit 的解析器(Parser)遇到非数字时会抛出异常或导致渲染失败。

核心原因

javax.swing.text.html.parser 包中的解析器(通常是 DocumentParserParserDelegator)在解析 CSS 属性或 HTML 属性值时,会调用 Float.parseFloat()Integer.parseInt() 等方法来转换数值,当遇到 NaNInfinity 或无效数字字符串(如空字符串、px 前缀等)时,会抛出 NumberFormatException

解决方案

方案 1:预处理 HTML 内容(推荐)

在将 HTML 设置到 JEditorPane 之前,使用正则替换掉所有 NaN 值:

String rawHtml = "<div style=\"width: NaNpx; height: 100px;\">内容</div>";
// 替换所有 NaN 值和无效数值(NaNpx、NaN、nullpx 等)
String cleanedHtml = rawHtml.replaceAll("\\bNaN\\b", "0")
                            .replaceAll("(?<=[\\d.])NaN", "")  // 处理 1.5NaN 情况
                            .replaceAll("(?<=\\b)NaN(?=px|%|em|rem|pt)", "0") // 处理 NaNpx
                            .replaceAll("(?<=\\b)Infinity(?=px|%|em)", "0")
                            .replaceAll("(?<=\\b)Infinity\\b", "0");
editorPane.setText(cleanedHtml);

NaN 出现在更复杂的位置(如 JavaScript 生成的属性),考虑更全面的清理:

public static String sanitizeNumericValues(String html) {
    // 移除所有 CSS 数值中的 NaN/Infinity
    return html.replaceAll("(?<=\\s)(NaN|Infinity)(?=\\s|;|\\}|\\b)", "0")
               .replaceAll("(NaN|Infinity)(px|%|em|pt|cm|mm|in|pc|ex|ch|rem|vw|vh|vmin|vmax)", "0$2")
               .replaceAll("(?<=[>:\\s])(NaN|Infinity)(?=[<:;\\s])", "0")
               .replaceAll("\\\\bNaN\\\\b", "0");
}

方案 2:自定义 HTMLEditorKit 并重写解析器(进阶)

如果无法预处理 HTML(例如内容来自动态源),可以继承 HTMLEditorKit 并替换解析器:

import javax.swing.text.html.*;
import javax.swing.text.html.parser.*;
public class SafeHTMLEditorKit extends HTMLEditorKit {
    @Override
    public Document createDefaultDocument() {
        Document doc = super.createDefaultDocument();
        // 设置自定义解析器
        ((HTMLDocument) doc).setParser(new SafeParser());
        return doc;
    }
    // 自定义解析器
    private static class SafeParser extends ParserDelegator {
        @Override
        public void parse(Reader r, HTMLEditorKit.ParserCallback cb, boolean ignoreCharSet) throws IOException {
            // 在解析前先过滤输入流中的 NaN 等非法数值
            BufferedReader br = new BufferedReader(r);
            String line;
            StringBuilder safeHtml = new StringBuilder();
            while ((line = br.readLine()) != null) {
                safeHtml.append(sanitizeLine(line)).append("\n");
            }
            // 用清理后的文本创建新 Reader
            StringReader cleanReader = new StringReader(safeHtml.toString());
            super.parse(cleanReader, cb, ignoreCharSet);
        }
        private String sanitizeLine(String line) {
            return line.replaceAll("\\bNaN\\b", "0")
                       .replaceAll("\\bInfinity\\b", "0")
                       .replaceAll("(?<=\\d\\.)NaN", ""); // 处理 1.5NaN
        }
    }
}

然后设置:

editorPane.setEditorKit(new SafeHTMLEditorKit());
editorPane.setContentType("text/html");

方案 3:捕获并忽略解析异常(不推荐但简单)

try {
    editorPane.setText(htmlContent);
} catch (Exception e) {
    // 虽然不理想,但至少不会崩溃
    System.err.println("HTML 解析失败: " + e.getMessage());
    // 尝试显示纯文本
    editorPane.setText("无法渲染此内容(包含非法数值)");
}

常见的 NaN 出现场景

场景 示例 处理方式
CSS 属性值 width: NaNpx 替换为 0px
百分比值 50% NaN% 替换为有效值
JavaScript 动态生成 <span style="margin: NaNem"> 预处理替换
空字符串转 NaN parseInt("") 导致 NaN 检查 HTML 生成逻辑
数学运算错误 0/0 导致 NaN 后端修复生成逻辑

建议

  1. 根本解决:检查生成 HTML 的后端逻辑,避免输出 NaN 值(通常是 JS 模板渲染或 Java 字符串拼接导致)。
  2. 通用方案:使用正则预处理是最简单有效的方法。
  3. HTML 非常大:考虑使用流式过滤而非一次性字符串替换,避免内存问题。

如果你能提供具体的 HTML 片段或错误堆栈信息,我可以给出更精准的替换正则或处理方案。

抱歉,评论功能暂时关闭!