Java中使用AntiSamy时的换行符不一致问题
这个问题我之前也碰到过,本质是AntiSamy会自动规范化换行符,导致你看到的“看起来一样”的字符串,底层的字符编码其实不一样,所以equals返回false。
问题根源
你的原始输入(来自GUI)大概率是Windows风格的换行符\r\n(回车+换行),而AntiSamy在清理HTML时,会按照HTML规范把所有换行格式(\r\n、\r、\n)统一转换成Unix风格的\n。虽然肉眼看文本完全一致,但两个字符串的字符序列已经不同了——一个是First line\r\nSecond line,另一个是First line\nSecond line,直接用equals自然不相等。
你可以用这段代码验证一下:
// 打印原始输入的每个字符编码 for (char c : value.toCharArray()) { System.out.printf("0x%04X ", (int) c); } System.out.println(); // 打印清理后内容的每个字符编码 for (char c : cr.getCleanHTML().toCharArray()) { System.out.printf("0x%04X ", (int) c); }
运行后你会看到,原始换行对应的是0x0D 0x0A(\r\n),而清理后的换行是0x0A(\n)。
解决方案
有两种思路可以解决这个问题:
1. 比较前统一换行格式
在比较前,把两个字符串的换行符都转换成同一种格式,比如统一为\n:
// 简单处理:只替换Windows换行 boolean isEqual = value.replace("\r\n", "\n").equals(cr.getCleanHTML()); // 更通用的处理:覆盖所有换行类型 String normalizedInput = value.replaceAll("\\r\\n|\\r|\\n", "\n"); String normalizedClean = cr.getCleanHTML().replaceAll("\\r\\n|\\r|\\n", "\n"); boolean isEqual = normalizedInput.equals(normalizedClean);
2. 调整AntiSamy配置(不推荐)
如果你一定要保留原始的换行格式,可以尝试修改AntiSamy的策略文件,不过这并不推荐——因为HTML规范本身就会统一处理空白字符,强制保留原始换行可能会导致输出的HTML在不同浏览器/环境下表现不一致。如果确实要尝试,可以检查策略文件中是否有控制空白字符处理的配置项,不过默认的AntiSamy行为是符合HTML标准的。
补充说明
AntiSamy依赖的HTML解析器(比如Neeko)会自动规范化空白字符,这是为了保证输出的HTML结构一致,避免因不同系统的换行格式导致的兼容性问题。所以遇到这种“看起来一样但equals不相等”的情况,首先就要考虑空白字符(换行、空格、制表符)的规范化问题。
内容的提问来源于stack exchange,提问作者Rodrigo Rapozo

