通过Java转义大量字符以在XHTML网页上显示

时间:2010-10-19 20:54:07

标签: java xml xhtml escaping

我有一个运行Java应用程序的嵌入式设备,它可以提供XHTML网页(我可以将这些页面写成XHTML之外的其他内容,但我现在的目标是这样)。

当收到我的应用程序处理的网页请求时,我的代码中会调用一个方法,其中包含有关请求的所有信息,包括显示页面的输出流。

在我的一个页面上,我想显示一个(日志)文件,最大可达1 MB。

我可以使用以下代码显示未转义的文件:

final PrintWriter writer; // Is initialized to a PrintWriter writing to the output stream.
final FileInputStream fis = new FileInputStream(file);
final InputStreamReader inputStreamReader = new InputStreamReader(fis);
try {
    writer.println("<div id=\"log\" style=\"white-space: pre-wrap; word-wrap: break-word\">");
    writer.println("    <pre>");
    int length;
    char[] buffer = new char[1024];
    while ((length = inputStreamReader.read(buffer)) != -1) {
        writer.write(buffer, 0, length);
    }
    writer.println("    </pre>");
    writer.println("</div>");
} finally {
    if (inputStreamReader != null) {
        inputStreamReader.close();
    }
}

这种方法运行良好,并在一两秒内显示整个文件(可接受的时间范围)。

此文件可以(实际上)包含无效XHTML的字符,最常见的是<>。所以我需要找到逃脱这些角色的方法。

我尝试的第一件事是CDATA部分,但是如记录here,它们在IE8中无法正确显示。

我尝试的第二件事是如下方法:

// Based on code: https://stackoverflow.com/questions/439298/best-way-to-encode-text-data-for-xml-in-java/440296#440296
// Modified to write directly to the stream to avoid creating extra objects.
private static void writeXmlEscaped(PrintWriter writer, char[] buffer, int offset, int length) {
    for (int i = offset; i < length; i++) {
        char ch = buffer[i];

        boolean controlCharacter = ch < 32;
        boolean unicodeButNotAscii = ch > 126;
        boolean characterWithSpecialMeaningInXML = ch == '<' || ch == '&' || ch == '>';

        if (characterWithSpecialMeaningInXML || unicodeButNotAscii || controlCharacter) {
            writer.write("&#" + (int) ch + ";");
        } else {
            writer.write(ch);
        }
    }
}

这正确地转义了字符(如果需要,我将扩展它以转义HTML无效字符),但是网页需要15秒以上才能显示,页面上的其他资源(图像,css样式表)间歇性地失败加载(我相信由于它们的请求超时因为处理器被挂起)。

我尝试在BufferedWriter前面使用PrintWriter以及以各种方式更改缓冲区大小(用于读取文件和BufferedWriter),没有改善。

有没有办法逃避所有不需要迭代流中每个字符的XHTML无效字符?如果没有办法加速我的代码足以在几秒钟内显示这些文件?

如果必须的话,我会考虑减小日志文件的大小,但我希望它们的大小至少为250-500 KB(理想的是1 MB)。

我已经有了一种方法来简单地下载日志文件,但我想在浏览器中显示它们以便进行简单的故障排除/细读。

如果有办法设置标题以便IE8 / Firefox只是将文件作为文本文件显示在浏览器中,我会认为这是另一种选择(并且整个页面都专用于没有任何类型的XHTML的文件)。


编辑:

在完成Cameron Skinner建议的change和性能测试之后,看起来转义的写入大约需要块编写版本的1.5-2倍。这不是什么,但我可能无法通过弄乱它来获得巨大的加速。

我可能只需要减少日志文件的最大大小。

3 个答案:

答案 0 :(得分:1)

你可以从commons-lang尝试StringEscapeUtils

StringEscapeUtils.escapeHtml(writer, string);

答案 1 :(得分:1)

您可以选择在网页内部托管的iframe内提供日志内容。 iframe的来源可以指向以文字形式提供内容的网址。

答案 2 :(得分:1)

一个小的改变(好吧,可能)显着提高速度是改变

writer.write("&#" + (int) ch + ";");

writer.write("&#");
writer.write((int)ch);
writer.write(";");

字符串连接非常昂贵,因为Java为每个+运算符分配一个新的临时字符串缓冲区,因此每次有一个需要替换的字符时,您都会生成两个临时缓冲区。

编辑:关于另一个答案的评论之一是高度相关的:找到慢速位的第一位。我建议测试没有要转义的字符的日志以及要转义的许多字符。

我认为你应该做出建议的改变,因为它只花费你几秒钟的时间。