我有一个运行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倍。这不是什么,但我可能无法通过弄乱它来获得巨大的加速。
我可能只需要减少日志文件的最大大小。
答案 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为每个+运算符分配一个新的临时字符串缓冲区,因此每次有一个需要替换的字符时,您都会生成两个临时缓冲区。
编辑:关于另一个答案的评论之一是高度相关的:找到慢速位的第一位。我建议测试没有要转义的字符的日志以及要转义的许多字符。
我认为你应该做出建议的改变,因为它只花费你几秒钟的时间。